delaycompress 是 logrotate 中与 compress 配合使用的参数,作用是延迟压缩最新一轮轮转的日志文件(如 .1),待下一次轮转时才将其压缩为 .gz;而仅用 compress 会立即压缩所有轮转出的旧日志。

delaycompress 是什么,和 compress 有什么区别
delaycompress 不是独立生效的参数,它必须和 compress 一起用,否则没意义。它的作用很具体:让最新一轮轮转出来的日志文件**不立即压缩**,而是等下一次轮转时,才把「上一轮」的文件压缩成 .gz。
比如你配置了 daily + rotate 7 + compress + delaycompress,那么每天轮转一次,第 1 天产生的 access.log.1 不会被 gzip;到第 2 天轮转时,access.log.1 才变成 access.log.1.gz,而新产生的 access.log.1(原当天的主日志)依然保持未压缩状态。
这样做的核心原因是:避免对正在被进程写入的日志做压缩操作——虽然 logrotate 默认会先 mv 再通知服务 reopen,但某些场景(如没配 postrotate 或服务未响应)下,旧文件句柄可能还被占用,直接压缩可能失败或卡住。
不加 delaycompress 会怎样
如果只写 compress,不写 delaycompress,那么每次轮转后,新生成的历史文件(如 access.log.1)会**立刻被 gzip 压缩**,变成 access.log.1.gz。
这在多数情况下能省空间,但有风险:
- 如果服务没及时 reload(比如 Nginx 没执行
kill -USR1),它还在往access.log.1写,而logrotate已把它压缩,就可能出现“写入已压缩文件”的异常(Linux 允许,但内容损坏、解压失败) - 某些监控工具或日志收集器(如 filebeat)依赖文件名匹配,看到
.gz就跳过,结果漏掉刚轮转但还没压缩的那轮日志 -
lsof | grep access.log.1查不到句柄,不代表它没被打开——有些进程用 fd 直接 hold 住,mv后仍可写,此时压缩会破坏一致性
什么时候该关掉 delaycompress
你明确知道以下三点,才可以安全去掉 delaycompress:
- 服务支持原子 reopen(Nginx、rsyslog、systemd-journald 都 OK,但自研 daemon 要验证)
- 配置了可靠的
postrotate/endscript,且每次都能成功执行(建议加&& true防止失败中断) - 不需要人工快速查看上一轮日志内容(比如
zcat access.log.1.gz | tail比tail access.log.1多敲几个字)
否则,保留 delaycompress 是更稳妥的选择——它多留一天明文,换来的是轮转过程的鲁棒性。
容易被忽略的细节:delaycompress 不影响 rotate 计数
rotate 7 数的是所有历史文件(含未压缩的 .1 和已压缩的 .2.gz 等),不是只数 .gz 文件。也就是说,delaycompress 不会让磁盘多占一倍空间——它只是把压缩动作往后推了一次轮转周期,最终保留的文件总数不变。
真正要注意的是:delaycompress 和 maxage 的交互。比如你设了 maxage 15,但某天因故障没跑 logrotate,那第 16 天补跑时,access.log.1(本该第 2 天压缩)可能已经超龄,logrotate 会直接删掉它,而不是先压缩再删——这个行为不会报错,也很难被监控捕获。

















