logrotate是一个旨在简化生成大量日志文件的系统管理的工具。它允许自动轮换、压缩、删除和邮件发送日志文件。每个日志文件可以按天、按周、按月处理,或当文件增长到指定大小时处理。使用文档可参见https://linux.die.net/man/8/logrotate。
logrotate 的日志轮转策略
日志文件命名策略
在轮转过程中,日志文件会依次被重命名,例如application.log->application.log.1->application.log.2。每次轮转后,旧的.1文件会被推到.2,而新的.1文件则是从最新的application.log文件生成的。
配置日志轮转规则
在/etc/logrotate.d目录下创建文件,为服务配置日志轮转规则,详细配置信息参见https://linux.die.net/man/8/logrotate。
下面给出了一个日志轮转规则的示例(注释仅为提示作用,实际编写时注释应该独占一行)。
/var/log/myservice.log {
monthly # 每月轮转
#size 4K # 每达到4K轮转,该配置与周期配置冲突
missingok # 如果日志文件不存在不会报错
rotate 12 # 日志文件在被删除或mail之前会轮换的次数。
maxsize 4K # 即使在时间周期内,达到4K轮转
compress # 压缩轮转的日志文件
delaycompress # 将上一个日志文件的压缩推迟到下一个轮换周期
notifempty # 文件为空时不轮转
su root root # 运行logrotate时的用户和组都为root
create 0640 root root # 轮转后创建新日志时的权限
}logrotate /etc/logrotate.d/<logconfig>立即根据规则轮转日志,-d选项输出调试信息且不执行实际轮转操作,-f选项忽略轮转条件、强制轮转文件。
默认轮转时的逻辑是:移动.log为.log.1并创建一个新文件.log;如果启用copytruncate,会先将.log复制到新位置.log.1,然后截断.log(内容清空)。下面从日志生产者和消费者的角度讨论该配置的影响。生产者是将日志写入文件的程序,它们可能是普通程序或Docker、K8s中的容器化程序;消费者是读取日志文件并处理的程序,例如Filebeat、Vector等程序会采集日志并转储到数据库中。
不启用copytruncate的影响
不启用时,轮转本质是在同一文件系统中移动文件,其inode和data block不变,程序仍可以通过原文件描述符读取、修改移动后的.log.1。
- 对于生产者,我们希望它将日志输出到新创建的
.log中,这需要它能探测到日志的轮转并打开新的.log(指向新的inode),这可能需要添加代码。- 如果通过日志库写入日志文件,一些库会自动更改输出。
- 如果通过重定向写入日志文件,无法主动应对日志轮转,需要重新启动。
- 对于消费者,我们希望它读取到原日志文件
.log.1的末尾后自动转读.log,大多数日志采集器都有这个能力。
启用copytruncate的影响
启用时,轮转是发生了文件的截断,程序可以继续写入截断后的.log。
- 对于生产者,截断不影响其继续写入文件
.log,但极端情况下会丢失数据(文件复制和截断之间有数据写入)。 - 对于消费者,它应该及时读取
.log.1中未处理完的内容(原.log中未处理完),然后继续处理截断后的.log。
logrotate 的定时启动
通常,logrotate是作为 cron任务 or systemd服务 每日执行一次的。除非处理标准是日志大小,并且logrotate被每天执行多次,或者使用了-f或--force选项,否则它不会在一天内多次修改一个日志文件。
logrotate 与 crond 系统
cron是 Linux 系统中以后台进程模式周期性执行命令或指定程序任务的服务软件。默认情况下,安装 Linux 后crond服务就会启动,定期(默认每分钟一次)根据其预设定的规则执行任务。一般可以在/etc/crontab中配置定时任务,默认已配置了时、日、周、月周期任务规则,仅需将脚本文件放入对应的目录即可。
# cat /etc/crontab | grep run-parts
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly
logrotate默认被配置日周期任务,可以在/etc/cron.daily/logrotate看到他的启动脚本。首先检查/run/systemd/system目录以判断systemd是否正在运行,是则脚本退出、不会执行 logrotate,避免在使用systemd定时器的系统上重复执行logrotate。
# skip in favour of systemd timer
if [ -d /run/systemd/system ]; then
exit 0
fi
# this cronjob persists removals (but not purges)
if [ ! -x /usr/sbin/logrotate ]; then
exit 0
fi
/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit $EXITVALUE
logrotate 与 systemd 系统
有systemd的系统中,logrotate被单元文件配置为systemd定时服务。查看单元文件/lib/systemd/system/logrotate.service,logrotate被设置为oneshot类型的服务,它只在系统启动时运行一次,而不是持续运行的守护程序。
[Unit]
...
[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf
...
定时任务的执行通过systemd timer实现,这些定时器类似于cron作业,但由systemd管理。查看文件/lib/systemd/system/logrotate.timer,OnCalendar=daily指定服务每天运行一次,.service和.timer通过基名称(basename)关联,在这里就是文件名中的logrotate。
[Unit]
...
[Timer]
OnCalendar=daily
AccuracySec=1
Persistent=true
...
