使用 logrotate 轮转日志

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中的容器化程序;消费者是读取日志文件并处理的程序,例如FilebeatVector等程序会采集日志并转储到数据库中。

不启用copytruncate的影响

不启用时,轮转本质是在同一文件系统中移动文件,其inodedata 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.servicelogrotate被设置为oneshot类型的服务,它只在系统启动时运行一次,而不是持续运行的守护程序。

[Unit]
...
[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf
...

定时任务的执行通过systemd timer实现,这些定时器类似于cron作业,但由systemd管理。查看文件/lib/systemd/system/logrotate.timerOnCalendar=daily指定服务每天运行一次,.service.timer通过基名称(basename)关联,在这里就是文件名中的logrotate

[Unit]
...
[Timer]
OnCalendar=daily
AccuracySec=1
Persistent=true
...

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

Index
滚动至顶部