0%

Linux下使用crontab定时清理日志文件

应用都会打印日志以便于调试和排查问题。一般都会每天新增一个文件打印当天的日志,虽然可能每个文件都不大,但是日积月累,随着日志文件的增多,历史日志文件也会占用大量的磁盘空间。

所以每天定时清除历史日志文件是必须要去做的事。

本文就是介绍在 Linux 下,如何使用 bash脚本 和 crontab定时任务 来清理日志文件

1. 删除日志的Bash脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
##################################################################
#
# 定时清理日志文件
#
##################################################################

# 安全删除,只是把文件 mv 操作,会有另外任务删除被移除的文件
alias jrm="sh /app/SFiles/remove.sh"

#### 日志文件所在路径

# 定义app, 只需要修改app的值就可以实现
app=cat

# echo 'app is : ' $app

path=/app/$app/logs

# echo 'logs file path is : ' $path

# 进入日志目录
cd $path

#### 删除7天前的日志

# 获取7天前的日期
# del_date=`date '+%Y-%m-%d'`

# echo $del_date

target_date=`date -d "-7 day" '+%Y-%m-%d'`

echo 'target date is : ' $target_date

#### 循环获取日志文件进行判断后删除
for n in `ls *.log* -1`;
do

# echo $n

# 获取文件最后一个 . 后的内容进行匹配判断
m=`echo $n | awk -F. '{print $(NF)}'`

# 从倒数第10位开始截取,如果不满10位,则为空
m=`echo ${m:(-10)}`

# echo $m

# 不符合条件的日志文件不删除
if [ ! "$m" ]; then
# echo 'IS NULL'
# echo 'file ' $n 'no need to delete'
continue
fi

# 7天之内的日志文件不删除
if [[ $m > $target_date ]]; then
# echo 'file ' $n ' no need to delete'
continue
fi

echo 'file ' $n ' need to delete'

jrm -rf $app $n
done

echo 'Clear log job finished'

脚本有比较清晰的注释了,如果需要清除另一个应用的日志文件,那么只需要修改 app 变量

如果日志文件路径不同,那么需要修改 path 变量

上述脚本针对的日志文件格式是 cat-biz.log.2019-05-08 的格式,也就是 ****.log.yyyy-MM-dd 格式的日志文件,如果格式不同,则需要相应修改

我们看到第一行脚本是:

1
alias jrm="sh /app/SFiles/remove.sh"

这行脚本的作用是在执行删除日志文件时,不希望直接使用 rm -rf ,直接使用该命令存在误删除风险

为了避免误删除的情况,实际执行的是 mv 操作,将需要删除的历史日志文件先移动到一个指定目录(类似windows的垃圾回收箱),随后另一个脚本会定时清空该目录

这样一旦发生了误删除,还有补救的机会,那就让我们来看下是如何操作的吧

2. 避免直接 rm -rf

先看下 /app/SFiles/remove.sh 里的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 定义安全删除的命令

# 打印参数个数
# echo $#

# 参数必须是3个,使用时如 jrm -rf cat cat-biz.log.2019-05-01
if [ $# != 3 ] ;then
echo 'args numbers must equal 3'
exit 1
fi

TRASH_BASE_DIR="/app/SFiles/.trash"

DATE=`date '+%Y%m%d'`

# echo $DATE

# echo $2

target_dir=$TRASH_BASE_DIR/$2/$DATE/

# echo $target_dir

if [ ! -e "$target_dir" ]; then

# 如果路径中有些文件夹不存在,则会自动创建
mkdir -p "$target_dir"
fi

mv $3 $target_dir

我们首先在 /app/SFiles 目录下创建一个新文件夹:.trash,之后所有需要被删除的历史日志文件都会放在这个文件夹中

用户执行 remove.sh 命令必须是 remove.sh -rf 应用名 具体的日志文件,例如:remove.sh -rf cat cat-biz.log.2019-05-01

这样脚本就会将该文件移动到 /app/SFiles/.trash/应用名/当前日期(yyyyMMdd格式)/ 目录下

3. 定时执行脚本

每天定时执行清除日志脚本我们需要用到 crontab

执行 crontab -e 命令,配置定时任务

1
10 1 * * * /app/vprex/clearlog.sh >/dev/null 2>&1

具体的 crontab 表达式请自行搜索,这里说两个遇到的问题

任务未运行

手动执行删除日志脚本可以正常运行,但是使用 crontab 定时执行就不行,有很多原因会造成这个情况,但我遇到的原因和下面这句话有关

1
alias jrm="sh /app/SFiles/remove.sh"

一开始这句话我是配置在环境变量文件中,但后来发现 crontab 执行时不会去找环境变量,所以就无法执行脚本中的

1
jrm -rf $app $n 

所以改成在清理日志脚本中先定义好 jrm 命令的别名

Maildir目录

crontab 定时执行任务后,会在脚本目录下自动创建 Maildir 目录

这主要是因为当 crontab 任务执行完毕后,系统会将任务日志完成的情况通过电子邮件的方式发给系统用户

所以在 crontab 脚本中最后要添加

1
>/dev/null 2>&1

这样就不会生成 Maildir 目录了

4. 清空 .trash 目录下的文件

使用 crontab -e 添加 清空 .trash 目录的任务,例如:

1
20 11 * * * rm -rf /app/SFiles/.trash/* >/dev/null 2>&1

参考

[1] https://blog.csdn.net/qq686867/article/details/79814855
[2] https://www.jianshu.com/p/8659275c11d0
[3] https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/crontab.html
[4] https://www.cnblogs.com/tankblog/p/6934987.html