logrotate

Table of Contents

1. logrotate 简介

logrotate 是日志分割工具。使用 logrotate ,日志文件都可被设置成每日,每周或每月轮转,也能在文件太大时立即轮转。

logrotate 支持的命令行参数如下:

$ logrotate --help
Usage: logrotate [OPTION...] <configfile>
  -d, --debug               Don't do anything, just test (implies -v)
  -f, --force               Force file rotation
  -m, --mail=command        Command to send mail (instead of `/bin/mail')
  -s, --state=statefile     Path of state file
  -v, --verbose             Display messages during rotation
  -l, --log=STRING          Log file
  --version                 Display version information

Help options:
  -?, --help                Show this help message
  --usage                   Display brief usage message

一般地, logrotate 使用 cron 来运行,其 cron 配置文件一般为:

$ cat /etc/cron.daily/logrotate
#!/bin/sh

/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0

2. logrotate 用法

2.1. logrotate 配置文件实例

logrotate 的配置文件位于 /etc/logrotate.conf,这个配置文件会加载目录 /etc/logrotate.d 中的所有配置文件。

下面以 Nginx 的 logrotate 配置文件为例来进行介绍。

安装 Nginx 后,默认有下面配置文件:

$ cat /etc/logrotate.d/nginx
/var/log/nginx/*log {
    daily                 # 每天轮转
    rotate 14             # 保留14个备份
    dateext               # 设置备份文件以当前日期为结尾,如xxx.log-20131216,否则是xxx.log-1这种格式
    missingok             # 如果 /var/log/nginx/*log匹配不到文件的话也不报错,直接跳过
    notifempty            # 当日志文件为空时,不进行轮转
    create 0644 nginx adm # 指定创建的新日志文件的 mode owner group;如果设置了copytruncate,则忽略create
    compress              # 备份时启用压缩,默认使用
    sharedscripts         # 备份完所有日志文件后,再执行下面脚本。默认是,每处理一个日志文件就执行一次脚本
    # postrotate指令用于指定在logrotate转储之后需要执行的指令,以endscript结束
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

默认,轮转备份的日志文件和当前日志文件在同一个目录中。下面是 nginx 运行一段时间后,/var/log/nginx 目录的文件列表:

$ sudo ls /var/log/nginx/
access.log              error.log
access.log-20180429.gz  error.log-20180429.gz
access.log-20180430.gz  error.log-20180430.gz
access.log-20180501.gz  error.log-20180501.gz
access.log-20180502.gz  error.log-20180502.gz

2.2. 立刻执行日志轮转

当你等不及 cron 调度 logrotate ,可以通过 -f--force 选项来立刻执行日志轮转:

$ sudo logrotate --force /etc/logrotate.d/your-cfg          # 没到时间就强制执行

2.3. 调试 logrotate

使用 -d--debug 选项仅输出执行的详细情况,而不会真正执行命令,以方便调试:

$ sudo logrotate --debug --force /etc/logrotate.d/your-cfg  # 不会真正执行

2.4. 应用程序重新打开日志文件

日志文件被轮转后,需要告诉应用程序重新打开日志文件。下面介绍两种方法。

2.4.1. 应用程序自己提供的功能(推荐)

postrotate 指令中使用应用程序自己提供的功能,如节 2.1 中就是采用的这种方法。

有些应用程序提供了重新打开日志文件的功能。比如 Nginx,支持使用 USR1 信号来通知 Nginx 重新打开日志文件的;又如,MySQL 可以通过 flush-logs 来重新打开日志文件的。

不过,有很多应用程序没有重新打开日志文件的功能,所以方法一不是万能的。

2.4.2. copytruncate

logrotate 提供的 copytruncate 指令采用的是先拷贝再清空的方式,整个过程中日志文件的操作句柄没有发生改变,所以不需要通知应用程序重新打开日志文件。

下面是使用 copytruncate 的实例:

/home/www/*.log {
    missingok
    nocreate
    daily
    dateext
    compress
    copytruncate      # 先拷贝再清空,不会改变文件句柄
    rotate 10
}

说明 1:在拷贝和清空之间有一个时间差,所以可能会丢失应用程序的部分日志。
说明 2:如果应用程序写日志文件时,没有用 O_APPEND 方式,会导致文件空洞。这是因为没有采用 O_APPEND 方式的话,当日志文件被清空后,应用程序会接着之前日志文件的偏移位置输出,这个位置之前会被 \0 填充,从而导致空洞。不过,这一点也不用太担心,因为应用程序写日志时一般都会采用 O_APPEND 方式打开文件。

Author: cig01

Created: <2017-06-04 Sun>

Last updated: <2020-05-10 Sun>

Creator: Emacs 27.1 (Org mode 9.4)