使用场景
接手的项目日志的量太大,经常让机器磁盘报警,频率非常高,查看后发现并不是所有的日志文件都很大,而是某几个日志文件比较大,使用的是DailyRollingFileAppender,每天都会产生一个大的日志文件,格式基本是文件名加日期,cndata.log.2016-09-27
,这几个日志文件也不太重要,所以想用定时任务当磁盘使用率到达一定的数量后自动删除这些大的日志文件。这是一个治标的办法,可以省去删日志的时间,但是日志这么多还是要优化下。
使用方法
在机器上执行 sudo crontab -u root -e
命令,在编辑窗口新增
*/10 * * * * /bin/sh /home/lq/delete_log.sh -c 80 -f hbase.log,cndata.log -p /home/admin/logs -b 1 -l 3
/home/lq/delete_log.sh 是脚本的路径,-c表示磁盘使用率到多少开始删除日志,-f表示需要删除的日志文件名,多个日志文件用逗号分隔,-p表示日志所在文件夹的路径,-b表示从哪天开始删除,1表示昨天,2表示前天,以此类推,-l表示需要删除几天的日志量。
我这边配置的表示每10分钟执行一次删除日志工作,如果磁盘容量到达80%,就删除昨天、前天、大前天的hbase.log和cndata.log日志
通过sudo crontab -u root -l
可以查看任务是否添加成功
通过sudo /sbin/service crond reload
命令可以手动重新加载定时任务
脚本代码(delete_log.sh)
#!/bin/sh
while getopts "p:c:f:b:l:" arg #选项后面的冒号表示该选项需要参数
do
case $arg in
p)
#日志路径
logPath=$OPTARG
;;
c)
#磁盘使用率到达多少开始删除日志
alarmCapacity=$OPTARG
;;
f)
#需要删除的文件名,多个用逗号分隔
deleteLogFileNames=$OPTARG
;;
b)
#开始删除的日期,1代表昨天,2代表前天,以此类推
dayBegin=$OPTARG
;;
l)
#需要删除的天数,如果dayBegin为1,dayLength为3,表示删除昨天、前天、大前天的日志
dayLength=$OPTARG
;;
?) #当有不认识的选项的时候arg为?
echo "unkonw argument"
exit 1
;;
esac
done
#默认删除三天 也就是删除昨天、前天、大前天的日志
if [ -z "$dayBegin" ]&&[ -z "$dayLength" ];then
dayBegin=1
dayLength=3
fi
if [ -z "$logPath" ]||[ -z "$alarmCapacity" ]||[ -z "$deleteLogFileNames" ]||[ -z "$dayBegin" ]||[ -z "$dayLength" ]
then
echo "arg is not valid"
exit 10
fi
#如果输入的路径最后没有斜杠,补上斜杠
if ! [[ "$logPath" =~ '/$' ]];then
logPath=${logPath}/
fi
dayLength=`expr $dayBegin + $dayLength`
#分隔需要删除的文件名
OLD_IFS="$IFS"
IFS=","
arr=($deleteLogFileNames)
IFS="$OLD_IFS"
#获取磁盘使用率
diskCapacity=`df -h / |awk '{print$5}'|grep '^[0-9][0-9]*%$'`
diskCapacity=${diskCapacity%?}
#临时目录,存放需要删除的日志文件
tmpDir=${logPath}logbak_`date +"%F"`
#定义任务日志,方便查询删除了哪些文件
resultLog=${logPath}/crontab.log
if [ ! -f "$resultLog" ];then
touch "$resultLog"
fi
#磁盘使用率操过用户输入的报警值,开始删除日志
if [[ $(echo "$diskCapacity>$alarmCapacity"|bc) -eq 1 ]];then
for((serialNumber=$dayBegin;serialNumber<$dayLength;serialNumber++))
do
serialNumberDayTime=`date -d"$serialNumber day ago" +"%F"`
for fileName in ${arr[@]}
do
preDeleteFile=${logPath}${fileName}.${serialNumberDayTime}
if [ -f "$preDeleteFile" ];then
if [ ! -d "$tmpDir" ];then
mkdir $tmpDir
fi
#把需要删除的日志放在临时目录下
mv $preDeleteFile $tmpDir
fi
done
done
#删除日志
date "+%G-%m-%d %H:%M:%S">>"$resultLog"
ls -l $tmpDir|grep -v total|awk '{print$9}'>>"$resultLog"
rm -rf $tmpDir
fi