日志轮转不是甩开tool直接删文件,而是把“准备空间”和“保留现场”两件事同时做对。很多计算节点的磁盘告警,根源不是日志多,而是轮转策略没跑通,今天直接围绕实际场景,把日志轮转如何保护磁盘这层窗户纸捅破。
日志轮转失效,多半是踩了这三个坑
先看两个最常见的现场:
- 计算节点跑了三个月,
/var/log目录占用从 2GB 涨到 40GB,df -h一看使用率 98%,但logrotate明明配了每周轮转。 - 某个Java服务每天吐出 6GB 日志,轮转文件保留7份,磁盘总占用反而比不轮转时更高。
行业内专家指出,这类问题九成出在轮转触发条件和文件句柄上,而不是轮转本身没生效,具体拆开看:
误判日志大小的机制
logrotate 的 size 参数只在cron触发轮转那一刻才去检查文件大小,并非实时监控,很多节点上的 cron 执行时间是凌晨3点,如果日志在凌晨4点开始暴涨,到第二天凌晨3点前已经写了 8GB,size 500M 的设置才会在下一次cron到来时才触发切割。
结果就是:磁盘眼看要满了,但 logrotate 还没到点上班。
copytruncate的隐性风险
copytruncate 在复制日志后立即清空原文件,但并不通知正在写的进程,日志文件描述符依然指向已清空的空间,之后进程继续在空洞上写数据,最终形成覆盖,更麻烦的是,copytruncate在复制与截断之间存在毫秒级窗口,高并发写入会丢失那几毫秒的日志,对排查故障是个小坑。
create模式(旧日志改名后新建文件)不会有数据丢失问题,但需要业务进程支持重新打开日志文件,像 nginx、MySQL这类自身支持日志重开的软件,建议优先用create模式;像有些自研服务不监听信号、不会重开日志文件的,才退而求其次用copytruncate。
轮转后磁盘不降反升
默认 compress 开启后,logrotate 会先轮转再压缩,如果节点磁盘空间仅够写入一次完整轮转文件,压缩动作会因为空间不足而失败,导致轮转出的文件原样躺在磁盘上,这也是为什么很多运维会看到:轮转完成、磁盘使用率没降、反而多了一个大文件。
计算节点日志把磁盘写满怎么解决
遇到日志暴增、磁盘告警,按下面顺序处理,最快稳住局面:
- 先定位:
找出占用最高的日志文件。du -sh /var/log/ | sort -rh | head
- 临时切割:直接对最大日志执行
logrotate -f /etc/logrotate.d/你的服务名,强制立即轮转。 - 修正配置:在轮转配置中同时指定
size和daily,避免单靠一个维度触发。 - 清出余量:如果磁盘已经满到写不进去,先删掉压缩时间最早的
.gz文件,别动未压缩的当前日志。 - 设置水位线:结合
monit或脚本,在磁盘使用率到 85% 时触发告警,到 92% 时自动执行一次强转。
真实场景中,某语音识别计算节点的 asr_trace.log 曾在一个小时内膨胀到 22GB,当时值班人员只调大了 size 阈值,反而让问题更严重,正确做法是:把size调低、把rotate份数调多,而不是寄希望于“等磁盘满之前切一次”。
logrotate maxsize和size的区别
这两个参数常混用,但行为差异很大:
| 参数 | 触发逻辑 | 适用场景 |
|---|---|---|
size 500M |
仅在轮转周期到达时检查文件大小,超过则轮转 | 日志增长节奏稳定,有固定高峰时段 |
maxsize 500M |
在轮转周期内文件达到大小时立即轮转,不受cron周期限制 | 日志量突发性强、不可预测的计算节点 |
maxsize是size的超集,它既保留cron周期限制,又增加“超过即切”的弹性,对计算节点来说,训练任务、批处理任务常在深夜或整点集中启动,日志瞬时暴涨的概率很大,因此优先使用maxsize比size更稳。
轮转时间设置的正确姿势
很多配置写 daily 就直接不管了,结果深夜任务日志从凌晨1点写到早上8点,daily轮转在凌晨3点把正在进行中的日志切了一半出去,查询问题时要翻两个文件才能对上一个时间片。
节点日志轮转时间设置的推荐方案是:把轮转时间安排在业务低谷期,具体做法是在 /etc/crontab 中单独定义logrotate的执行时间:
30 2 root /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
这样把轮转动作固定在凌晨2:30,避开大多数批处理任务的起止点,对于有固定任务运行窗口的节点,根据具体时段向前推 30分钟 即可。
一份可落地的日志轮转配置参考
以计算节点上最常见的
Python训练脚本和推理服务为例,给出能直接改改用的模板:
/path/to/compute-node/logs/.log {
su root root
daily
maxsize 500M
rotate 7
compress
delaycompress
missingok
notifempty
dateext
dateformat -%Y%m%d-%H%M%S
copytruncate
}
参数解释:
maxsize 500M:当日志在24小时内涨到500M时,不等cron周期直接切割。rotate 7:保留最近7轮,配合compress,磁盘占用控制在 500M × 7 × 约10%压缩比 ≈ 3.5GB。delaycompress:下一次轮转时再压上一轮的日志,防止业务进程还在写旧文件时被压缩。dateext + dateformat:让日志文件名带上精确到时分秒的时间戳,出问题时能快速定位到秒。
这个配置用在大模型推理节点上,日志从每天 30GB 稳定在 4GB 磁盘占用,用 copytruncate 也是因为推理进程不响应USR1信号,不会主动重新打开日志文件,只能复制截断,这是用退化方案解决兼容问题的典型场景。
监控日志本身是否轮转
日志轮转配置好不算完,轮转没运行同样常见,检查命令:
cat /var/lib/logrotate/logrotate.status | grep 你的日志路径
如果状态文件里显示的轮转时间超过一周,但日志文件仍在增长,说明cron没有执行logrotate,或者执行了但 size 条件一直未满足,此时用 logrotate -v /etc/logrotate.d/你的配置 跑一次调试模式,能看到每条规则的匹配过程。
journald也需要单独管
很多计算节点用 systemd 启动任务,journald 自己会存一份日志,但默认日志容量上限是系统盘空间的10%,如果系统盘本身只有 50GB,journald最多会占用 5GB,这部分默认不归 logrotate 管,需要单独设置:
journalctl --vacuum-size=100M
journalctl --vacuum-time=7d
第一条把journald日志压缩清理到 100MB,第二条删除7天前的日志,上面的命令是临时生效,重启后失效,永久配置在 /etc/systemd/journald.conf 中改:
SystemMaxUse=200M
MaxRetentionSec=7day
改完重启 systemctl restart systemd-journald。
日志切割需要避免的几个操作
以下做法在节点上很常见,但实际会引发反弹:
- 直接删除正在写入的日志文件,进程的fd仍指向已删除文件,磁盘空间并不释放,必须
让进程重开fd或用kill -USR1
truncate -s 0清空。 - 压缩正在写入的日志,压缩同时大量读盘,和业务抢I/O,计算任务耗时直接拉高。
- 一个轮转规则管所有目录,计算节点上常同时跑数据预处理、模型训练、推理服务,日志增速差异巨大,共用一份配置会造成“一刀切”,要么切太勤,要么切不动。
日志轮转后磁盘空间何时真正释放
这是计算节点上最容易误解的地方。logrotate把access.log改成access.log.1,并不会立刻释放磁盘空间,因为写日志的进程还开着原来的文件描述符,删除或改名对进程来说“感知不到”。
只有这两种情况,空间才会真正释放:
- 进程收到信号并重新打开日志文件(如
nginx -s reopen),原本的fd关闭,磁盘空间释放。 - logrotate配置了
copytruncate,先复制再截断,复制完截断的那一刻就释放了空间但代价是丢失两次操作间隙的极少量日志。
这也是为什么轮转配置文件里写了create还不够,业务服务本身必须支持日志重开,像gunicorn需要发HUP信号,nginx需要USR1,Kafka、Elasticsearch这类JVM进程有自己的内部日志轮转机制,外部再有logrotate会冲突。
正确做法是先确认业务进程的日志打开方式,再决定用create还是copytruncate,而不是每一步都靠copytruncate兜底万一那个应用同时在写多个日志文件,会有丢失数据风险。
常见问题速查
为什么logrotate轮转以后,磁盘空间没有减少?
多数原因是有进程仍持有旧fd,用lsof | grep deleted找出这些进程,让它们重新加载配置,或重启,少数原因是compress因空间不足失败,生成的未压缩轮转文件占据等量空间。
日志轮转配置里copytruncate和create怎么选?
取决于业务进程是否支持重新打开日志文件,nginx、MySQL、Redis这类支持的,用create保证不丢日志;不支持的自研脚本、部分Python常驻进程,用copytruncate,两者在日志量超过单文件2GB时,处理大文件都偏重,尽量让单个日志文件小一点再轮转。
怎么判断日志轮转策略适不适合自己的节点?
连续观察三个周期,轮转高峰期磁盘占用不超过总空间70%,轮转后能回撤60%以上的日志占用,业务日志能覆盖到最近至少3天的排障需求达到这三个指标就说明策略是合适的,否则就回到maxsize和rotate份数上重新调。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/641059.html





