先看现象。CentOS 7 上 logrotate 每天由 cron.daily 调用,某天开始 /var/log/messages 里反复出现 error: stat of /var/log/nginx/access.log failed: No such file or directory,此后日志再没被切过。

这类报错背后常见的原因有几处,逐个排除就行。有人手工 rm 了日志文件,nginx 还持有 fd 往已删除的 inode 里写。另一种情况是站点目录改过,logrotate 配置里的路径与实际不一致。

少数情况下是目录被改成 700 且属主不是 root,logrotate 以 root 跑也 stat 不到。

动手时先看配置里的真实路径

logrotate -d /etc/logrotate.d/nginx | head -20

接着让进程重新打开文件

nginx -s reopen; ls -l /proc/$(cat /run/nginx.pid)/fd | grep access

补回被删的文件

install -m 640 -o www -g adm /dev/null /var/log/nginx/access.log

手动强制轮转一次

logrotate -f /etc/logrotate.d/nginx && ls -l /var/log/nginx/

同事提醒我看一下最近一次发布,时间点确实对得上。

命令输出我都留了记录,免得改完记不清原来的值。

改之前先确认了最近有没有人动过配置,避免白查一遍。

怎么算真的好了,看的是同一批现象。目录里出现 access.log.1 与新的 access.log,lsof 显示 nginx 写的是新 inode,第二天 logrotate 日志里没有 error。

补一句。日志文件被 rm 后 df 不会降、轮转也会失效,两个问题一起出现;改配置前用 -d 空跑一遍,能省掉一半试错。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189