您的位置:首页 > 运维架构 > Shell

linux shell 脚本 历史文件清理脚本,按天,按月,清理前N天的历史文件,删除指定大小历史文件,历史文件归档清理

2017-05-05 16:18 603 查看
不知道大家那有没有要清理的这个事情。需要清理目录历史文件。可能后续也会有很多其他地方需要清理历史文件,可能会用到。

我这两天空闲写了个脚本,清理比较方便,有要进行清理的大量历史文件的话可以用。

脚本用到的命令只有linux才有,像solaris等就不支持,所以只能在linux上运行。如果是nas存储的话,可以挂载到一个linux主机上跑脚本清理。

另外,脚本查找文件用的是ls,但是ls也有最大文件的限度(大概10w以内),如果每天文件很多,每天都是10w+的,运行可能提示文件数过多无法ls。

还有,脚本内有个默认的限制,就是清理的文件的创建日期是跟文件名上的时间是相同的,如果是不同的话,是不会清理的,这是为了避免清理错了。

我写了两个版本的清理脚本,一个是直接清理文件的clearfile.sh,一个是把文件按天/月进行归档(归档成文件夹或压缩包形式)clearfile_ar.sh:

(一)单纯清理文件使用clearfile.sh

文件名是带有时间戳的文件,类似如下(或其他时间格式,后面描述)



按天/月清理:修改脚本内的CLEAR_TYPE参数,D是天,M是月

如果是按月的话,脚本按你输入的月份进行整月清理,不会看你输入的天的时间

清理指定期间内所有文件

./clearfile.sh/wls/investop/tmp/
20170515 20170516

清理指定期间内固定大小文件(ls -l显示的大小)

./clearfile.sh
/wls/investop/tmp/ 20170515
20170516 40

其他文件日期格式清理

脚本默认(TRUNC_DATE_FLAG参数为N)是清理上面截图这类格式的,没有任何间隔符的文件名。

如果文件名是有其他间隔符的,如*2017_05_16*这种的。



首先需要调整下脚本里的trunc()方法,把标黄的年月日之间的分隔符改成需要的分隔符(按天和按月两种哦)



然后再设置TRUNC_DATE_FLAG参数为Y,来让脚本使用你指定的日期格式清理

[b](二)归档方式清理历史文件,使用clearfile_ar.sh[/b]

使用方式与clearfile.sh相同,唯一不同的是要设置脚本里的DEL_FLAG参数。

按天/月清理同clearfile.sh

清理指定期间内所有文件同clearfile.sh

清理指定期间内固定大小文件 同clearfile.sh

其他文件日期格式清理 同clearfile.sh

模式1:DEL_FLAG=N

脚本只会把文件按天/按月归档到以时间命名的文件夹内,如



模式2DEL_FLAG=Y

把文件归档成压缩文件*tar.gz,并删除归档的文件夹



PS,对于大量需要清理的目录,可以写一个非常简单的脚本来批量执行,类似



但是要去掉脚本里的是否确认执行这个反馈,否则脚本执行还是要你输入Y。



[b]~~~~~~~~~~~~~~~~~~脚本如下~~~~~~~~~~~~~~~~~~[/b]

clearfile.sh

#!/bin/bash
################################
##参数设置
################################
TODAY=`date +%Y%m%d`
DATE_BEGIN=`date +%Y%m%d`
DATE_END=`date +%Y%m%d`
DATE_FORMATION="%Y%m%d"
FILESIZE=""
COUNTING=0

#需要手工设置,按月清理不会根据输入日期的天清理,只能清理整个月。
CLEAR_TYPE=M
#需要手工设置,是否需要转换日期格式,需要的话,要根据格式设置trunc()方法
TRUNC_DATE_FLAG=N

if [ -f count.tmp ]
then
echo "" > count.tmp
fi

################################
##日期格式转换,eg:trunc 20170512
################################
trunc()
{
if [ "D" = "$CLEAR_TYPE" ]
then
OPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})(.{2})$/\1_\2_\3/g'`
else
OPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})$/\1_\2/g'`
fi
}

################################
##按日清理递归
################################
dayclear()
{
echo "================================"
echo "day clear working on $DATE_END"

doclear $DATE_END
priday $DATE_END

if [ $DATE_END -lt $DATE_BEGIN ]
then
echo "================================"
echo "Total cleard : $COUNTING "
echo "dayclear end"
return
fi

dayclear
}

################################
##按月清理递归
################################
monthclear()
{
echo "================================"
echo "clearfun working on $DATE_END"

doclear $DATE_END
primonth $DATE_END

if [ $DATE_END -lt $DATE_BEGIN ]
then
echo "================================"
echo "Total cleard : $COUNTING "
echo "monthclear end"
return
fi

monthclear
}

################################
##前一日日期,eg:priday 20170421
################################

priday()
{
SEC=`date -d $1 +%s`
PRI_SEC=$[${SEC}-86400]
PRI_DAY=`date -d @${PRI_SEC} +%Y%m%d`
DATE_END=$PRI_DAY
}

################################
##前一月日期,eg:primonth 201704
################################

primonth()
{
#TMP_D=`echo $1 | cut -c 1-6`
#TMP_D=${TMP_D}"01"
TMP_D=`echo $1`"01"
SEC=`date -d $TMP_D +%s`
PRI_SEC=$[${SEC}-86400]
PRI_MON=`date -d @${PRI_SEC} +%Y%m`
DATE_END=$PRI_MON
}

################################
##清理文件
################################

doclear()
{
#默认的日期格式,如20170512,201705
THE_DATE=$1
OPR_DATE=$1
#转换OPR_DATE的日期格式,如2017-05-12,2017-05
if [ "Y" = ${TRUNC_DATE_FLAG} ] ; then
trunc $1
fi

echo "clearing"
if [ "" == "${FILESIZE}"  ]
then
#ROW=`ls -l *${OPR_DATE}* | awk  '{ print $9;output="ls -l "$9;system(output);}' | wc -l`
ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | grep -v archive | awk -v date_str=${THE_DATE} 'BEGIN{count=0}{if (date_str==$6) {count+=1;output="rm "$7;system(output);}}END{oo="echo "count" > count.tmp";system(oo);}'
ROW=`cat count.tmp`
COUNTING=$[ $COUNTING + $ROW ]
else
#ROW=`ls -l *${OPR_DATE}* | awk -v the_size=${FILESIZE} '{if ($5==the_size) {output="ls -l "$9;system(output)}}' | wc -l`
ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | awk -v the_size=${FILESIZE} -v date_str=${THE_DATE} 'BEGIN{count=0}{if (the_size==$5 && date_str==$6) {count+=1;output="rm "$7;system(output);}}END{oo="echo "count" > count.tmp";system(oo);}'
ROW=`cat count.tmp`
COUNTING=$[ $COUNTING + $ROW ]
fi
echo "clear $THE_DATE finished, clear file $ROW "
}

#######################################
## main function
## 判断参数是否正确,可以输入如下:
## 清理所有文件:clear 20150601 20161231
## 清理固定大小字节文件:clear 20150601 20161231 40
## 清理固定大小字节文件:clear 20150601 20161231 40
#######################################

#清理所有文件,
if [ $# -ne 3 ] && [ $# -ne 4 ]
then
echo "请输入正确的参数"
echo "如清理/nfsc/hipo/bak目录下,从2015年4月1号到2016年12月31号的所有文件(默认按日清理):clearfile /nfsc/hipo/bak 20150401 20161231"
echo "或清理清理/nfsc/hipo/bak目录下,从2015年4月1号到2016年12月31号的大小为40字节的文件(默认按日清理):clearfile /nfsc/hipo/bak 20150401 20161231 40"
exit 1

else
DATE_BEGIN=$2
DATE_END=$3
FILESIZE=$4

date -d $2 2>&-
ERR1=$?
date -d $3 2>&-
ERR2=$?
if [ $ERR1 -eq 1 ] || [ $ERR2 -eq 1 ]; 	then
echo "date formation error, input the correct date string like 20170131."
exit 1
elif [ $DATE_BEGIN -gt $DATE_END ]; 	then
echo "BEGIN DATE is later than END DATE, please correct."
exit 1
elif [ $TODAY -lt $DATE_END ]; 	then
echo "END DATE is later than NOW DATE, please correct"
elif [ ! -d $1 ]; 	then
echo "DIR $1 does not exist."
exit 0
fi
fi

cd $1
THEDIR=`pwd`
echo ">>>>clear the DIR $THEDIR "
echo ">>>>clear file between $DATE_BEGIN and $DATE_END."
if [ "" == "${FILESIZE}"  ]; then
echo ">>>>every size of the files will be clear"
else
echo ">>>>clear filesize only is ${FILESIZE}"
fi
if [ "D" == "${CLEAR_TYPE}"  ]; then
echo ">>>>clear set by DAY"
else
echo ">>>>clear by MONTH"
fi

read -p "please confirm the information above,enter Y to continue, other to exit : " ANWSER
#确认继续
if [ ! -n "$ANWSER" ] || [ $ANWSER != Y ]
then
echo "exit"
exit 0
fi

echo "[`date +%Y%m%d-%H%M%S`]==START=="

if [ "D" = "$CLEAR_TYPE" ]
then
echo "DAY clear begin "
DATE_FORMATION="%Y%m%d"
dayclear
else
echo "MONTH clear begin "
DATE_BEGIN=`echo $2 | cut -c 1-6`
DATE_END=`echo $3 | cut -c 1-6`
DATE_FORMATION="%Y%m"
monthclear
fi

echo "[`date +%Y%m%d-%H%M%S`]==END=="


clearfile_ar.sh

#!/bin/bash
################################
##参数设置
################################
TODAY=`date +%Y%m%d`
DATE_BEGIN=`date +%Y%m%d`
DATE_END=`date +%Y%m%d`
DATE_FORMATION="%Y%m%d"
FILESIZE=""
COUNTING=0

#需要手工设置,按月清理不会根据输入日期的天清理,只能清理整个月。
CLEAR_TYPE=M
#需要手工设置,是否删除归档的文件,只保留压缩文件
DEL_FLAG=N
#需要手工设置,是否需要转换日期格式,需要的话,要根据格式设置trunc()方法
TRUNC_DATE_FLAG=N

if [ -f count.tmp ]
then
echo "" > count.tmp
fi

################################
##日期格式转换,eg:trunc 20170512
################################
trunc()
{
if [ "D" = "$CLEAR_TYPE" ]
then
OPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})(.{2})$/\1_\2_\3/g'`
else
OPR_DATE=`echo $1 | sed -r 's/^(.{4})(.{2})$/\1_\2/g'`
fi
}

################################
##按日清理递归
################################
dayclear()
{
echo "================================"
echo "day clear working on $DATE_END"

doclear $DATE_END
priday $DATE_END

if [ $DATE_END -lt $DATE_BEGIN ]
then
echo "================================"
echo "Total cleard : $COUNTING "
echo "dayclear end"
return
fi

dayclear
}

################################
##按月清理递归
################################
monthclear()
{
echo "================================"
echo "clearfun working on $DATE_END"

doclear $DATE_END
primonth $DATE_END

if [ $DATE_END -lt $DATE_BEGIN ]
then
echo "================================"
echo "Total cleard : $COUNTING "
echo "monthclear end"
return
fi

monthclear
}

################################
##前一日日期,eg:priday 20170421
################################

priday()
{
SEC=`date -d $1 +%s`
PRI_SEC=$[${SEC}-86400]
PRI_DAY=`date -d @${PRI_SEC} +%Y%m%d`
DATE_END=$PRI_DAY
}

################################
##前一月日期,eg:primonth 201704
################################

primonth()
{
#TMP_D=`echo $1 | cut -c 1-6`
#TMP_D=${TMP_D}"01"
TMP_D=`echo $1`"01"
SEC=`date -d $TMP_D +%s`
PRI_SEC=$[${SEC}-86400]
PRI_MON=`date -d @${PRI_SEC} +%Y%m`
DATE_END=$PRI_MON
}

################################
##清理文件
################################

doclear()
{
#默认的日期格式,如20170512,201705
THE_DATE=$1
OPR_DATE=$1
#转换OPR_DATE的日期格式,如2017-05-12,2017-05
if [ "Y" = ${TRUNC_DATE_FLAG} ] ; then
trunc $1
fi

#创建归档文件夹
echo "clearing"
if [ ! -d ${THE_DATE}"archive" ] ;then
mkdir "${THE_DATE}"archive
ERR=$?
if [ 0 != ${ERR} ]; 	then
echo "failed to create archive dir under "`pwd`
exit 0
fi
echo "created the archive directory ${THE_DATE}archive"
chmod 777 ${THE_DATE}"archive"
else
echo "the archive directory already exist ${THE_DATE}archive"
fi

#如果要删除历史的归档文件,判断是否已经存在过历史文件的压缩包
if [ -f "${THE_DATE}archive.tar.gz" ] && [ "Y" = "${DEL_FLAG}" ] ;then
echo "file ${THE_DATE}archive.tar.gz already exits, and again you choose to archive the file which had been archived ,this will cause the old tar.gz file tobe overwirted."
echo "you should confirm the date parameter you input, or you can mv the exits *.tar.gz file to other directory."
exit 0
fi

if [ "" == "${FILESIZE}"  ]
then
ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | grep -v archive | awk -v date_str=${THE_DATE} 'BEGIN{count=0;}{if (date_str==$6) {count+=1;output="mv "$7" "date_str"archive/";system(output);}}END{oo="echo "count" > count.tmp";system(oo);}'
if [ "Y" = "${DEL_FLAG}" ] ; then
tar -cf - ${THE_DATE}"archive/" | gzip > ${THE_DATE}"archive.tar.gz"
rm -rf ${THE_DATE}"archive/"
fi
ROW=`cat count.tmp`
COUNTING=$[ $COUNTING + $ROW ]
else
ls -ld --time-style +${DATE_FORMATION} *${OPR_DATE}* | grep -v archive | awk -v the_size=${FILESIZE} -v date_str=${THE_DATE} 'BEGIN{count=0;}{if (the_size==$5 && date_str==$6) {count+=1;output="mv "$7" "date_str"archive/";system(output);}}END{oo="echo "count" > count.tmp";system(oo);}'
if [ "Y" = "${DEL_FLAG}" ] ; then
tar -cf - ${THE_DATE}"archive/" | gzip > ${THE_DATE}"archive.tar.gz"
rm -rf ${THE_DATE}"archive/"
fi
ROW=`cat count.tmp`
COUNTING=$[ $COUNTING + $ROW ]
fi

echo "clear $THE_DATE finished, clear file $ROW "
}

#######################################
## main function
## 判断参数是否正确,可以输入如下:
## 清理所有文件:clear 20150601 20161231
## 清理固定大小字节文件:clear 20150601 20161231 40
## 清理固定大小字节文件:clear 20150601 20161231 40
#######################################

#清理所有文件,
if [ $# -ne 3 ] && [ $# -ne 4 ]
then
echo "请输入正确的参数"
echo "如清理/nfsc/hipo/bak目录下,从2015年4月1号到2016年12月31号的所有文件(默认按日清理):clearfile /nfsc/hipo/bak 20150401 20161231"
echo "或清理清理/nfsc/hipo/bak目录下,从2015年4月1号到2016年12月31号的大小为40字节的文件(默认按日清理):clearfile /nfsc/hipo/bak 20150401 20161231 40"
exit 1

else
DATE_BEGIN=$2
DATE_END=$3
FILESIZE=$4

date -d $2 2>&-
ERR1=$?
date -d $3 2>&-
ERR2=$?
if [ $ERR1 -eq 1 ] || [ $ERR2 -eq 1 ]; 	then
echo "date formation error, input the correct date string like 20170131."
exit 1
elif [ $DATE_BEGIN -gt $DATE_END ]; 	then
echo "BEGIN DATE is later than END DATE, please correct."
exit 1
elif [ $TODAY -lt $DATE_END ]; 	then
echo "END DATE is later than NOW DATE, please correct"
elif [ ! -d $1 ]; 	then
echo "DIR $1 does not exist."
exit 0
fi
fi

cd $1
THEDIR=`pwd`
echo ">>>>clear the DIR $THEDIR "
echo ">>>>clear file between $DATE_BEGIN and $DATE_END."
if [ "" == "${FILESIZE}"  ]; then
echo ">>>>every size of the files will be clear"
else
echo ">>>>clear filesize only is ${FILESIZE}"
fi
if [ "D" == "${CLEAR_TYPE}"  ]; then
echo ">>>>clear set by DAY"
else
echo ">>>>clear by MONTH"
fi

read -p "please confirm the information above,enter Y to continue, other to exit : " ANWSER
#确认继续
if [ ! -n "$ANWSER" ] || [ $ANWSER != Y ]
then
echo "exit"
exit 0
fi

echo "[`date +%Y%m%d-%H%M%S`]==START=="

if [ "D" = "$CLEAR_TYPE" ]
then
echo "DAY clear begin "
DATE_FORMATION="%Y%m%d"
dayclear
else
echo "MONTH clear begin "
DATE_BEGIN=`echo $2 | cut -c 1-6`
DATE_END=`echo $3 | cut -c 1-6`
DATE_FORMATION="%Y%m"
monthclear
fi

echo "[`date +%Y%m%d-%H%M%S`]==END=="


欢迎各位博友提出更新意见。

谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: