线上服务跑久了,日志文件会越来越大:占磁盘、查找慢、备份困难,甚至能把磁盘写满导致服务异常。
logrotate是 Linux 上最常用的日志自动化管理工具,能按规则切割、压缩、保留、删除日志文件,并通过cron定时调度自动执行。
此文章用/www/binlog/demo_log/demo.log 举例,讲清楚如何配置并验证:每天切一次,同时文件达到 100MB 也触发轮转,最多保留 5 份,老日志 gzip 压缩,且不重启 Go 进程也能切。
1. logrotate 能做什么
logrotate 的核心能力:
-
轮转触发条件
- 按时间:daily / weekly / monthly
- 按大小:size 100M
- 两者可组合(常用:按天 + 大小兜底)
-
压缩与清理
compress:gzip 压缩旧日志节省空间rotate N:保留 N 份,其余自动删除
-
安全性与容错
missingok:日志文件不存在也不报错notifempty:空日志不切,减少碎文件- 权限控制:避免因为权限问题导致轮转失败或误操作
系统上通常由 cron(或 systemd timer)定时执行 /usr/sbin/logrotate,你只需要写好规则。
2. 配置文件结构
logrotate 常见两种配置来源:
- 主配置:
/etc/logrotate.conf - 子配置目录:
/etc/logrotate.d/(推荐把业务规则放这里)
我们把本服务的规则放在:
/etc/logrotate.d/demo_log
3. 实战配置
目标日志文件:
/www/binlog/demo_log/demo.log
配置内容如下:
/www/binlog/demo_log/demo.log {
daily
size 100M
rotate 5
compress
delaycompress
missingok
notifempty
copytruncate
su root root
}
4. 每个参数是什么意思
daily
- 每天轮转一次
- 常见配合
rotate 7/14/30做“按天保留”
size 100M
- 文件达到 100MB 也会触发轮转
- 适合日志波动大的业务:不至于当天写爆
组合效果:正常情况每天切一次,但如果一天内写得特别多,达到 100MB 时也会切(由 logrotate 的调度频率决定——例如每天跑一次,则“size”会在下一次执行时生效;如果要更快响应,需要提高调度频率)。
rotate 5
- 最多保留 5 份旧日志
- 超过就自动删除(等价于“最多保留 5 次轮转历史”)
compress
- 旧日志使用 gzip 压缩
- 省空间非常明显(文本日志压缩率通常很高)
delaycompress
- 最新切出来那一份先不压缩
- 好处:更安全(有些程序可能仍在短时间内访问刚切割出来的文件)
missingok
- 日志文件不存在也不报错
- 防止首次部署、路径变化导致 cron 报警
notifempty
- 空日志不切割
- 避免生成一堆
xxx.1的空文件
copytruncate(核心)
- 不重启进程也能切日志
- logrotate 会把当前日志复制出一份作为轮转文件,然后把原文件截断为 0
- 适用于 Go/PHP/Java 等程序没有实现日志 reopen(SIGHUP)机制时
取舍:
copytruncate会“复制 + 截断”,极端高并发写日志时可能产生极小概率的丢行风险;如果你的程序支持USR1/HUPreopen(例如 nginx),更推荐postrotate发信号让进程重新打开新文件,但多数自研 Go 程序日志文件输出不一定做了 reopen,这时copytruncate是最省事且通用的方案。
su root root
- 以 root 用户/组执行轮转动作
- 防止因权限不足导致轮转失败(尤其日志目录权限比较严格时)
5. 调试与验证(上线前必做)
5.1 强制轮转一次(验证配置是否生效)
sudo logrotate -f /etc/logrotate.d/milk_tea_bin_log
5.2 建议先用 debug 模式看看会做什么(不真正执行)
sudo logrotate -d /etc/logrotate.d/milk_tea_bin_log
如果你看到类似 “rotating pattern” “compressing log” 等输出,说明规则被正确解析。
6. 确认业务程序在跑(排查误判)
你的笔记里是通过进程名确认:
ps -ef | grep milk_tea_bin_log | grep -v grep
如果日志没增长/没轮转,先确认进程是否在跑、是否真的写的是这个文件路径。
7. 常见坑点总结
-
配置项拼写错误会直接失效 你笔记里出现过
delaycompressda、missingoksu这种连写,logrotate 会解析失败或忽略,所以一定要保持每行一个指令、拼写正确。 -
“size + daily”并不是实时触发 轮转是否执行取决于 logrotate 的调度频率(cron 可能是每天一次)。 如果你希望“超过 100MB 很快就切”,需要把 logrotate 的执行频率提高(例如每小时跑一次),但这属于系统调度层面。
-
copytruncate 的极小丢行风险 对绝大多数业务日志可接受;若你对日志完整性极端敏感,建议改成“程序支持 reopen + postrotate 发信号”的方式。
8. 最终可用配置
如果希望更“保守”(比如保留 7 份),只需调整一行:
rotate 7