logrotate对通配符路径(如/var/log/apps/*.log)会逐个展开并独立判断轮转条件,而非整体处理;需加missingok防中断,推荐加notifempty和sharedscripts,且标准版不支持递归通配符。

通配符匹配日志时,logrotate 会为每个匹配文件单独轮转
logrotate 对 /var/log/apps/*.log 这类通配符路径的处理方式是:先展开所有匹配到的文件(如 app1.log、app2.log),再对每个文件**独立判断是否满足轮转条件**(比如是否过期、是否达到 size)。它不会把它们当做一个整体来处理。
这意味着:如果某天只有 app1.log 满足 daily 条件,而 app2.log 刚刚切过,那只有前者会被轮转——这点容易被误认为“没生效”。
-
missingok必须加,否则某个匹配文件不存在就会中断整个通配符块的执行 -
notifempty建议加上,避免空日志反复创建.1文件却无内容 - 若多个匹配文件共用同一 postrotate 脚本(比如 reload 同一个服务),必须加
sharedscripts,否则脚本会被执行 N 次
/var/log/**/*.log 这种递归通配符是否可靠
标准 logrotate(截至 2026 年)**不原生支持 ** 递归匹配**。**你看到的配置示例多来自较新发行版的 patched 版本或文档误导。实际运行时,/var/log/**/*.log 会被 shell 展开失败,logrotate 将报错或静默跳过。
真正可移植的做法是显式列出目录,或用多个规则覆盖:
- 写成
/var/log/nginx/*.log、/var/log/tomcat/*.log等分开条目 - 或统一收口到一个父目录下(如
/var/log/allapps/*.log),再用单层* - 若必须跨多级,可用 shell wrapper 脚本生成临时配置,但会增加维护复杂度
匹配到不该切的日志文件怎么办
通配符太宽泛(比如 /var/log/*.log)极易误伤——可能把 installer.log 或调试用的 debug-20260908.log 也卷进去,导致误删或干扰人工排查。
安全做法是收窄范围:
- 优先用具体路径 + 明确文件名,如
/var/log/nginx/access.log和/var/log/nginx/error.log分开写 - 若必须通配,用更精确后缀或前缀,例如
/var/log/myapp/*_service.log - 搭配
olddir把旧日志移到隔离目录,避免和当前日志混在一起 - 首次上线前务必用
logrotate -d /etc/logrotate.d/yourconf看 debug 输出,确认匹配列表是否符合预期
copytruncate 和 sharedscripts 组合使用时的坑
当用通配符匹配多个日志(如 /var/log/myapp/*.log),又启用了 copytruncate,且需在轮转后重载服务,这两个参数的配合非常关键。
典型错误是漏掉 sharedscripts,导致:
- logrotate 先对
a.log执行copytruncate→ 清空 a.log - 再执行一次
postrotate(reload 服务)→ 服务重新打开 a.log - 接着对
b.log执行copytruncate→ 清空 b.log - 再执行一次
postrotate→ 服务再次 reload,可能丢掉刚写入 b.log 的少量日志
正确写法必须包含 sharedscripts,确保所有匹配文件完成 copytruncate 后,只 reload 一次服务。否则,服务在多次 reload 间隙可能丢失日志或产生竞态。

















