Linux logrotate 高级配置技巧

9次阅读

rotate 和 maxage 不冲突,logrotate 同时检查二者,任一不满足即删除;rotate 按数量保留归档,maxage 按时间统一清理。

Linux logrotate 高级配置技巧

logrotate 配置文件里 rotatemaxage 同时设了,哪个优先?

两者不冲突,但作用完全不同:rotate 控制保留多少个归档文件(按数量),maxage 控制文件最多保留多少天(按时间)。logrotate 会同时检查这两个条件,** 只要任一条件不满足,对应日志就立刻被删掉 **。

常见错误是以为设了 rotate 7 就够了,结果日志生成不规律,某天没写日志,过了 30 天才又写,这时 maxage 30 就会把那个“老但合法”的归档干掉——而 rotate 根本管不到它。

  • rotate 7:只管“最近生成的 7 个归档”,不管它们多老
  • maxage 30:对所有匹配的日志归档统一检查“创建时间是否超 30 天”
  • 真实场景建议两个都设,尤其监控类服务日志,避免磁盘被长期静默的日志占满

dateext 时为什么 dateformat 不能随便写?

dateext 开启后,logrotate 默认用 -%Y%m%d 命名归档(如 access.log-20241015)。想改格式必须配 dateformat,但注意: 它只支持 strftime 的有限子集,且不同 logrotate 版本支持程度不同

常见坑:用 %s(秒级时间戳)或 %N(纳秒)会导致配置加载失败,报错 error: bad dateformat;某些旧版(如 CentOS 7 自带的 3.8.x)甚至不认 %Y,只认 %y(两位年份)。

  • 安全写法:dateformat -%Y%m%ddateformat -%y%m%d
  • 避免用:%s%F(部分版本不支持)、%Z(时区,易出错)
  • 验证方法:运行 logrotate -d /etc/logrotate.conf 看 debug 输出里归档名是否符合预期

脚本里执行 systemctl reload nginx 失败,但手动跑却 OK

logrotate 默认以 root 身份运行,但它的环境变量极简(几乎没 $PATH),也 ** 不读取 shell profile**。所以你在终端能直接敲 systemctl,logrotate 却找不到命令,报 /bin/sh: systemctl: not found

更隐蔽的问题是:某些 systemd 版本要求 systemctl 必须在特定 cgroup 或 dbus 上下文里调用,而 logrotate 的子 shell 不提供这些。

  • 绝对路径必写:postrotate 里用 /usr/bin/systemctl reload nginx,别省略
  • 加环境兜底:postrotate 开头加 export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  • 如果 reload 还失败,改用 kill -USR1 $(cat /var/run/nginx.pid)(前提是 nginx 支持该信号重载配置)

多个配置文件里定义同一日志路径,谁生效?

logrotate 按字母顺序读取 /etc/logrotate.d/ 下的文件,** 后加载的配置会覆盖先加载的同名路径规则 **。比如 /etc/logrotate.d/nginx/etc/logrotate.d/myapp 都写了 /var/log/nginx/access.log,那 myapp 里的配置最终生效。

这很容易导致线上行为和预期不符——你以为改的是 nginx 配置,实际被另一个文件覆盖了。debug 时仅看单个文件根本发现不了问题。

  • 查加载顺序:ls -1 /etc/logrotate.d/ | sort
  • 查最终生效规则:logrotate -d /etc/logrotate.conf 2>&1 | grep "considering log file" -A 10
  • 最佳实践:一个日志路径只在一个配置文件里定义,用注释标明归属,别图省事复用

最麻烦的不是语法写错,是配置散落在不同文件里,还靠字母序隐式覆盖——这种问题得翻完整目录才能定位。

text=ZqhQzanResources