logrotate压缩失败会中止轮转,导致旧日志滞留、新日志持续追加,最终引发磁盘爆满;常见原因包括gzip缺失、磁盘空间不足、selinux限制或/tmp noexec;修复需先禁用compress临时恢复轮转,再验证并安装/配置压缩命令。

logrotate 压缩失败本身不会直接占满磁盘,但会导致轮转卡住、旧日志堆积、新日志持续追加——这才是磁盘爆满的真正原因。
压缩失败时 logrotate 实际发生了什么
logrotate 在 compress 阶段调用 gzip(或 zstd)失败后,默认行为是中止本次轮转流程,不删除原始日志、不创建新空文件、也不执行 postrotate。结果就是:原 access.log 继续被服务写入,而上一轮该归档的 access.log.1 还躺在那里没被压缩,access.log.2 也还在……所有“待归档”文件都滞留,且全部保持未压缩状态。
常见触发点包括:gzip 命令不存在、磁盘空间不足(连临时压缩空间都不够)、SELinux 拒绝执行、或 /tmp 被挂载为 noexec 导致压缩器无法运行。
快速恢复:先绕过压缩,释放写入能力
- 临时注释掉配置里的
compress和delaycompress,保留rotate、size、create等核心项 - 确保
notifempty已启用,避免空日志触发无意义轮转 - 手动强制跑一次:
sudo logrotate -f /etc/logrotate.d/nginx(替换为你的服务名) - 观察是否成功生成
access.log.1、清空access.log并重建权限;若成功,说明问题确在压缩环节
修复压缩本身:别只装 gzip,要验证它能跑通
很多系统缺省没装 gzip,或装了但不在 PATH 中(尤其容器或精简镜像)。logrotate 不报错,只静默跳过压缩。
- 检查命令是否存在:
which gzip;若无,运行sudo apt install gzip(Debian/Ubuntu)或sudo yum install gzip(RHEL/CentOS) - 测试能否执行:
echo "test" | gzip > /tmp/test.gz && gunzip -c /tmp/test.gz,确认无权限或环境错误 - 若用
zstd替代(更省 CPU),需显式指定:compresscmd /usr/bin/zstd+uncompresscmd /usr/bin/unzstd - SELinux 用户加一句:
sharedscripts,并确认上下文允许:ls -Z /usr/bin/gzip,必要时restorecon -v /usr/bin/gzip
为什么 delaycompress 反而容易引发空间问题
delaycompress 的本意是“这次轮转先不压 .1,等下次轮转时再压”,但它依赖前一次轮转成功完成。一旦某次失败,.1 就永远卡在未压缩状态,后续每次轮转又新增一个未压缩的 .2、.3……最终多个 GB 的未压缩归档堆在目录里。
更稳妥的做法是去掉 delaycompress,改用 compress + minsize 1M(防止极小文件也压缩浪费 CPU),或直接接受首次压缩延迟——只要确保压缩命令本身可靠。
真正危险的不是压缩失败那一刻,而是没人去看 /var/lib/logrotate/logrotate.status 里各日志的最后轮转时间,以及 logrotate -d 输出里那句不起眼的 compress: not compressing old log (gzip failed)。











