notifempty是控制空日志文件是否跳过轮转的唯一有效配置,显式声明时遇0字节文件即跳过重命名、压缩、创建及postrotate等全部操作;默认行为为空文件仍照常轮转。

logrotate 的 notifempty 是控制空文件是否轮转的唯一有效配置
logrotate 本身不“切割”日志(它不拆分文件内容),而是按规则归档重命名。所谓“对空日志不执行切割”,实际意思是:当目标日志文件大小为 0 字节时,跳过本次轮转流程——不重命名、不压缩、不创建新文件、不触发 postrotate。
这个行为由 notifempty 控制,且它必须显式写入配置块中。注意:ifempty 不是合法参数名,logrotate 不识别;默认行为是“空文件也轮转”,等价于隐式启用 ifempty,但你不能靠“不写任何东西”来实现跳过——必须明确写 notifempty。
-
notifempty:遇到空文件,直接跳过该文件的整个轮转流程 - 不写
notifempty(即默认):空文件照常轮转(debug.log→debug.log.1,再新建空debug.log) - 写
noifempty:无效配置,logrotate 启动时会报错并忽略该行(验证过 3.18.x ~ 3.21.x 版本)
配置示例与常见错误组合
假设你要让 /var/log/myapp/app.log 在为空时不轮转,同时保留日常归档逻辑:
/var/log/myapp/app.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 0644 myapp myapp
}
关键点:
- 必须把
notifempty和daily(或其他时间/大小条件)放在同一配置块内,它不作用于全局 - 不要和
copytruncate混用:后者用于避免应用丢失写入句柄,但它会在轮转前拷贝内容,导致“空文件”几乎不会出现;若真用了copytruncate,notifempty实际上很难生效 - 如果同时写了
size 10M和notifempty,只有当文件非空且 ≥10M 时才触发轮转;空文件哪怕超过 10M(不可能,但逻辑上)也不会触发
如何验证 notifempty 是否生效
手动测试最可靠,别依赖 cron 时间等待:
- 清空日志:
truncate -s 0 /var/log/myapp/app.log - 强制运行并查看详细输出:
logrotate -vf /etc/logrotate.d/myapp - 观察输出中是否包含类似
notice: skipping /var/log/myapp/app.log because of notifempty的提示 - 检查文件状态:
ls -la /var/log/myapp/app.log*—— 若只看到app.log,没出现app.log.1,说明跳过成功
注意:如果输出里有 error: stat of /var/log/myapp/app.log failed: No such file or directory,说明你漏写了 missingok,logrotate 因找不到文件而中断,根本没走到 notifempty 判断逻辑。
容易被忽略的兼容性细节
notifempty 在所有主流 logrotate 版本(RHEL/CentOS 7+, Ubuntu 18.04+,Debian 10+)中都稳定支持,但它不解决以下问题:
- 它只判断文件大小是否为 0,不检查文件是否被其他进程锁定或正在写入中
- 如果日志文件存在但 inode 被回收(如应用 crash 后残留空文件),
notifempty仍会生效,但后续轮转可能因权限或路径问题失败 - 它不抑制
prerotate脚本执行——即使跳过了轮转,只要配置了prerotate且文件存在,脚本仍会运行(这是设计行为,不是 bug)
真正要绕过一切操作,得靠外部 wrapper 或改用 size 1k 这类更激进的触发条件,但那就脱离了 notifempty 的原始语义了。

















