Introduction简介
Logrotate 是一个用来管理日志文件的工具,可以帮我们自动压缩日志,清理日志,让我们的磁盘不至于爆满
一般情况下linux系统都预装了这个日志管理工具,如果是二般的情况就先手动安装一下吧
Logrotate Configuration 配置文件
Ubuntu下我们可以在如下两个地方找到所有的与logrotate相关的配置文件:
/etc/logrotate.conf
:这个文件中包含了一些默认的配置,并且一半会include下边的路径下的所有的配置文件/etc/logrotate.d/
: 这个文件夹是所有我们的logrotated配置文件所在的位置,按照文件名进行区分,例如一半情况下会有如下文件bootlog chrony syslog wpa_supplicant yum.
默认情况下,logrotate.conf 回设定按照7天为周期的的配置,我们找一个系统自带的例子看一下配置文件的写法
- cat /etc/logrotate.d/apt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/var/log/apt/term.log { rotate 12 monthly compress missingok notifempty } /var/log/apt/history.log { rotate 12 monthly compress missingok notifempty } |
这个配置文件包含了两个模块,分别定义了/var/log/apt路径下两个日志文件的配置,两个配置文件参数完全相同,如果有一些参数我们没有指定,那么配置文件会自动继承/etc/logrotate.conf中的配置,我们详细看一下每一项:
rotate 12
: 保留12个旧的文件monthly
: 每个月执行一次rotate操作compress
: 压缩我们的旧的日志文件,默认情况下会使用gzip压缩,当然也可以自己指定missingok
: 不输出错误日志notifempty
: 如果日志为空则不进行rotate操作
更多的参数设置可以参考 man logrotate
创建一个新的logrotate
如果我们想新增一个需要logrotate帮我们管理的日志文件我们有两个选资额:
- 在/etc/logrotate.d/目录下创建一个新的配置文件,默认情况下,logrotate会以root 的身份每天运行
- 如果我们不想使用系统自带的配置,例如我们不想使用root用户,或者我们不希望每天执行,我们想每个小时执行,我们需要额外创建新的配置文件及路径
我们详细的了解下两种方式的添加方式
使用 /etc/logrotate.d/
We want to configure log rotation for a fictional web server that puts an access.log
and error.log
into /var/log/example-app/
. It runs as the www-data
user and group.
如果我们想对一个路径/var/log/example-app/下的access.log(用户组为 www-data)进行管理
首先我们创建一个新的文件:
- sudo nano /etc/logrotate.d/example-app
例子:
1 2 3 4 5 6 7 8 9 10 11 12 |
/var/log/example-app/*.log { daily missingok rotate 14 compress notifempty create 0640 www-data www-data sharedscripts postrotate systemctl reload example-app endscript } |
几处特殊的地方:
create 0640 www-data www-data
: 这行的意思是每次rotate完成以后会创建一个新的空的文件,并且用户组是我们想要的www-datasharedscripts
: 每个脚本只执行一次,无论我们上边的正则匹配几个日志文件(*.log),如果这个目录下有有两个匹配到的日志文件,我们不设置这个值,每个文件rotate完后都会触发一次下边的脚本postrotate
toendscript
: 这段的脚本是每次rotate完后调用的脚本,例如,我们把旧文件rotate完并且创建了新的空的文件以后,我们需要重启服务让服务来写入新文件中,否则服务还是会写到旧文件中,这个问题设计的问题就不深入探讨了,注意一点,postrotate执行的时间是在压缩之前,因为压缩可能很耗费时间,我们需要我们的程序立刻切换写入的文件,如果你想在压缩完以后跑一些命令,可以使用lastaction模块
我们可以通过如下命令进行测试,不会真正的修改,只会模拟:
- sudo logrotate /etc/logrotate.conf –debug
设置一个特例的情况
假设我们有一个用户sammy 启动了一个app, 生成的日志都保存在/home/sammy/logs/文件夹下,我们想每个小时进行rotate,所以,我们需要/etc/logrotate.d意外的目录配置我们的需求
创建一个新的文件:
- nano /home/sammy/logrotate.conf
文件内容:
1 2 3 4 5 6 7 |
/home/sammy/logs/*.log { hourly missingok rotate 24 compress create } |
1 |
<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 16px; background-color: #ffffff;">上边配置文件额意思是: 每个小时执行,压缩并且保存24个旧的文件,并且创建新的日志文件代替旧的文件</span> |
准备测试换件:
- cd ~
- mkdir logs
- touch logs/access.log
这样我们有两个空的日志文件了
因为日志文件属于sammy,我们不需要sudo,但是我们确实需要指定一个状态文件,状态文件就是用来记录logrotate上一次都干了啥,这样logrotate就知道下次做什么了
我们可以执行如下命令
1 2 |
logrotate /home/<span class="highlight">sammy</span>/logrotate.conf --state /home/<span class="highlight">sammy</span>/logrotate-state --verbose |
1 2 3 4 5 6 7 8 9 |
reading config file /home/sammy/logrotate.conf Handling 1 logs rotating pattern: /home/sammy/logs/*.log hourly (24 rotations) empty log files are rotated, old logs are removed considering log /home/sammy/logs/access.log log does not need rotating |
--verbose
会打印详细的信息
如果我们查看一下状态文件,我们可以看一下状态文件的内容:
- cat /home/sammy/logrotate-state
1 2 3 |
logrotate state -- version 2 "/home/sammy/logs/access.log" 2017-11-7-19:0:0 |
剩下的我们就可以让crontab 来帮我们每个小时执行这个命令了:
- crontab -e
1 2 |
14 * * * * /usr/sbin/logrotate /home/sammy/logrotate.conf --state /home/sammy/logrotate-state |
强制执行的命令:
1 |
logrotate --force /etc/logrotate.d/nginx |
关于新的log文件的两种创建方式,可以参考https://jin-yang.github.io/post/logrotate-usage.html ,写的非常详细易懂
create
这也就是默认的方案,可以通过 create 命令配置文件的权限和属组设置;这个方案的思路是重命名原日志文件,创建新的日志文件。详细步骤如下:
- 重命名正在输出日志文件,因为重命名只修改目录以及文件的名称,而进程操作文件使用的是 inode,所以并不影响原程序继续输出日志。
- 创建新的日志文件,文件名和原日志文件一样,注意,此时只是文件名称一样,而 inode 编号不同,原程序输出的日志还是往原日志文件输出。
- 最后通过某些方式通知程序,重新打开日志文件;由于重新打开日志文件会用到文件路径而非 inode 编号,所以打开的是新的日志文件。
如上也就是 logrotate 的默认操作方式,也就是 mv+create 执行完之后,通知应用重新在新文件写入即可。mv+create 成本都比较低,几乎是原子操作,如果应用支持重新打开日志文件,如 syslog, nginx, mysql 等,那么这是最好的方式。
不过,有些程序并不支持这种方式,压根没有提供重新打开日志的接口;而如果重启应用程序,必然会降低可用性,为此引入了如下方式。
copytruncate
该方案是把正在输出的日志拷 (copy) 一份出来,再清空 (trucate) 原来的日志;详细步骤如下:
- 将当前正在输出的日志文件复制为目标文件,此时程序仍然将日志输出到原来文件中,此时,原文件名也没有变。
- 清空日志文件,原程序仍然还是输出到预案日志文件中,因为清空文件只把文件的内容删除了,而 inode 并没改变,后续日志的输出仍然写入该文件中。
如上所述,对于 copytruncate 也就是先复制一份文件,然后清空原有文件。
通常来说,清空操作比较快,但是如果日志文件太大,那么复制就会比较耗时,从而可能导致部分日志丢失。不过这种方式不需要应用程序的支持即可。
参考地址:
https://jin-yang.github.io/post/logrotate-usage.html
Latest posts by Zhiming Zhang (see all)
- aws eks node 自动化扩展工具 Karpenter - 8月 10, 2022
- ReplicationController and ReplicaSet in Kubernetes - 12月 20, 2021
- public key fingerprint - 5月 27, 2021