记一次logrotate自动切割日志不成功问题排查

问题描述

环境:

  • 操作系统:ubuntu 14.04.4 LTS

  • 内核版本:4.2.0-27-generic

问题描述:在 /etc/logrotate.d/ 中新增加了切割日志的配置后,本应由 crontab 调用 logrotate 执行的日志分割在第二天查看时发现并未进行操作。

思路

  1. 使用 logrotate -d /etc/logrotate.d/mongod 调试运行,查看是否配置有误

  2. 使用 logrotate -fv /etc/logrotate.d/mongod 强制执行,查看日志是否分割

  3. 查看 crontab 日志、logrotate 日志

logrotatecrontab 中自动执行的大致流程图如下

一、执行logrotate查看运行结果

  • 执行 logrotate -d /etc/logrotate.d/mongod

    shell
    1
    2
    3
    4
    5
    6
    7
    8
    # logrotate -d /etc/logrotate.d/mongod
    reading config file /etc/logrotate.d/mongod
    Handling 1 logs
    rotating pattern: /var/log/mongodb/*.log after 1 days (180 rotations)
    empty log files are not rotated, old logs are removed
    considering log /var/log/mongodb/mongod.log # 开始处理mongod.log
    log does not need rotating # 因为时间未到,不需要更动!
    not running postrotate script, since no logs were rotated

看上去好像没什么问题

  • 强制执行 logrotate -fv /etc/logrotate.d/mongod

    shell
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # logrotate -fv /etc/logrotate.d/mongod
    reading config file /etc/logrotate.d/mongod
    Handling 1 logs
    rotating pattern: /var/log/mongodb/*.log forced from command line (180 rotations)
    empty log files are not rotated, old logs are removed
    considering log /var/log/mongodb/mongod.log
    log needs rotating
    rotating log /var/log/mongodb/mongod.log, log->rotateCount is 180
    dateext suffix '-20200108'
    glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
    glob finding logs to compress failed
    glob finding old rotated logs failed
    copying /var/log/mongodb/mongod.log to /var/log/mongodb/mongod.log-20200108
    truncating /var/log/mongodb/mongod.log # 截断日志
    running postrotate script # 运行相关脚本

看结果强制执行是可以执行的,那么只能接着往下排查

二、查看crontab

查看crontab日志

有日志记录情况

查看日志,发现有相关执行记录:

shell
1
2
# grep -w "cron.daily" /var/log/cron.log
Jan 8 06:25:01 ubuntu-ngiam-6 CRON[11875]: (root) CMD (test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ))

通过日志知道 cron 成功执行了的,直接跳至三、查看logrotate

无日志记录情况

默认情况下 ubuntu 下并未开启 crontab 日志,CentOS 下启动有相关日志

开启 crontab日志请参考:linux下开启crontab日志

  1. 先查看 crontab 的是否有相关任务计划

    命令:cat /etc/crontab

    /etc/crontab
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # /etc/crontab: system-wide crontab
    # Unlike any other crontab you don't have to run the `crontab'
    # command to install the new version when you edit this file
    # and files in /etc/cron.d. These files also have username fields,
    # that none of the other crontabs do.
    SHELL=/bin/sh
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    # m h dom mon dow user command
    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 )
    #
  2. 查看 cron.daily 中是否包含 logrotate

    命令:cat /etc/cron.daily/logrotate

    /etc/cron.daily/logrotate
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #!/bin/sh

    # Clean non existent log file entries from status file
    cd /var/lib/logrotate
    test -e status || touch status
    head -1 status > status.clean
    sed 's/"//g' status | while read logfile date
    do
    [ -e "$logfile" ] && echo "\"$logfile\" $date"
    done >> status.clean
    mv status.clean status

    test -x /usr/sbin/logrotate || exit 0
    /usr/sbin/logrotate /etc/logrotate.conf

一路看下来发现 crontablogrotate配置并无异常,并且 crontab 是正确的定时执行了的,看来只能接着查看 logrotate 日志了。

三、查看logrotate

  1. 确认 /etc/logrotate.conf 中是否 include /etc/logrotate.d

    shell
    1
    2
    # grep -w "include" /etc/logrotate.conf
    include /etc/logrotate.d
  2. 再次确认 mongod 配置文件是否正确的位于上述的 /etc/logrotate.d 文件中

    命令:cat /etc/logrotate.d/mongod

    /etc/logrotate.d/mongod
    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
    /var/log/mongodb/*.log {
    # 添加日志后缀;格式为:YYYYMMDD
    dateext
    # 按天轮询:daily;按周轮询:weekly;按月轮询:monthly;按年轮询:yearly
    daily
    # 忽略执行错误,例如无法找到问题
    missingok
    # 存档保留最大份数(每轮询一次算一份)
    rotate 180
    # 完成分割的日志使用gzip归档
    compress
    # 与compress一起使用,指示logrotate不要将近期的归档文件压缩,压缩在下一次轮询
    delaycompress
    # 如果日志文件为空,轮询不会进行
    notifempty
    # 创建新的.log副本后,截断源.log文件
    copytruncate
    # 将循环日志文件保持在特定目录。该目录必需与现有日志文件在同一文件系统。
    # olddir /data/log-bak/
    sharedscripts
    # 在分割日志时执行命令
    postrotate
    [ -f /var/run/mongod.pid ] && kill -USR1 `cat /var/run/mongod.pid`
    endscript
    }

配置并无异常,并且最开始强制执行也能成功。只能接着查看相关日志了

shell
1
2
# grep -w "mongod" /var/lib/logrotate/status
"/var/log/mongodb/mongod.log" 2020-1-8-6:0:0

可以看到有相关的日志记录。

后面根据网上查找资料得知问题根本原因就出现在这个 /var/lib/logrotate/status 文件中

/var/lib/logrotate/status 这个文件用以记录日志文件的最后处理日期。 每次执行 logrotate,其都会检查这个文件,如果发现配置周期内已经执行了切分, 就不会再次切分。

比如配置文件写了 weekly,且昨天刚刚切分了文件,则这次切分会被 logrotate 记录进文件 /var/lib/logrotate/status。 在此后一周内,无论手动执行 logrotate 命令,还是通过 cron 执行,都不会再次执行切分动作。(如果使用 -v 参数打印执行详情,会发现要处理的日志文件下有 log does not need rotating 这句)

如果指定 -f (force) 参数执行 logrotate 命令, 则会强制再次执行切分。

当然以上都是配置了日志按时间周期切分的情况, 按文件大小切分的配置不受此影响

因此,在第一次为某日志文件(假设为 /var/logs/nginx/access.log )配置了 logrotate 时,由于 /var/lib/logrotate/status 这个文件里没有 /var/logs/nginx/access.log 这个文件的记录,所以 logrotate 不知道是否要切分该文件。于是在第一天时,logrotate 仅把 /var/logs/nginx/access.log 这个文件记录在案,其他啥也没做。

  • CentOS下日志文件路径为:/var/lib/logrotate/logrotate.status

解决方法

等待第二天系统自动切割日志,用上所述新添加的配置项第一天是不会切分的。

如果需要切分,建议手动使用 logrotate -f logfile 强制切分。

评论

:D 一言句子获取中...

加载中,最新评论有1分钟缓存...