logrotate daily不生效的真正原因是其依赖/var/lib/logrotate/status中记录的最后成功轮转时间,而非系统时间或cron调度时刻;首次配置后若未真正完成轮转(如被notifempty或missingok跳过),status文件不更新,daily条件永不满足;/etc/cron.daily/logrotate实际由anacron控制,在3–22点间随机执行且要求间隔满86400秒才触发,手动-f强制执行会绕过该机制导致状态不同步。

logrotate daily 不生效的真正原因
daily 不代表“每天零点执行”,而是指“距离上次成功轮转满 24 小时才触发”。它依赖 /var/lib/logrotate/status 文件中记录的最后执行时间,而不是系统当前时间或 cron 的调度时刻。首次配置后,哪怕你当天手动运行过 logrotate -f,只要没真正完成一次轮转(比如因 notifempty 或文件不存在跳过),status 文件就不会更新,后续 daily 判断永远不满足条件。
/etc/cron.daily/logrotate 并不保证每天整点运行
实际执行时间由 anacron 控制,而非标准 cron。查看 /etc/anacrontab,你会发现类似这样的配置:
START_HOURS_RANGE=3-22 1 5 cron.daily nice run-parts /etc/cron.daily
这意味着:系统会在每天 3:00–22:00 之间随机选一个时间点运行 /etc/cron.daily/logrotate,且该任务必须在上一次成功执行后间隔至少 1 天(anacron 的 1 天 = 86400 秒)才会再次触发。所以即使你看到 cron 日志里有执行记录,也可能因 anacron 认为“还没到 24 小时”而直接跳过轮转逻辑。
为什么手动执行 logrotate -vf 能切,但 daily 不行
常见现象:手动跑 logrotate -vf /etc/logrotate.d/nginx 立刻切割成功,但第二天 /etc/cron.daily/logrotate 执行后却没动静。这是因为:
-
logrotate -vf强制(-f)忽略status时间判断,直接执行; - 而
/etc/cron.daily/logrotate默认调用的是logrotate -s /var/lib/logrotate/status /etc/logrotate.conf,严格依赖状态文件; - 如果上一次轮转被
missingok+ 文件不存在跳过,或被notifempty+ 日志为空拦截,status文件时间戳不会更新,daily 条件永远不成立。
怎么确认 daily 是否真被触发了
不要只看 cron 日志是否执行,要看 logrotate 是否真的做了事:
- 检查
/var/lib/logrotate/status文件末尾对应配置的最后时间:grep nginx /var/lib/logrotate/status; - 对比该时间与当前时间差是否 ≥24 小时;
- 用
logrotate -d /etc/logrotate.d/nginx模拟 dry-run,看输出里是否有rotating pattern和renaming行——没有就说明被规则拦下了; - 注意
dateyesterday参数:如果你的 cron.daily 在凌晨 2 点运行,但日志名要体现“昨天”的日期,就必须加这个选项,否则dateext会生成今天日期的文件名,容易造成误判。
最易被忽略的一点:logrotate 的 “daily” 是状态驱动,不是时间驱动。它不关心日历上的“天”,只认 status 里那个精确到秒的时间戳。改配置、删 status、换参数都得同步更新这个锚点,否则一切设置都是静默失效。

















