Logrotate :不重启 Go 进程也能安全切割日志

0 阅读4分钟

线上服务跑久了,日志文件会越来越大:占磁盘、查找慢、备份困难,甚至能把磁盘写满导致服务异常。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 常见两种配置来源:

  1. 主配置:/etc/logrotate.conf
  2. 子配置目录:/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/HUP reopen(例如 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. 常见坑点总结

  1. 配置项拼写错误会直接失效 你笔记里出现过 delaycompressdamissingoksu 这种连写,logrotate 会解析失败或忽略,所以一定要保持每行一个指令、拼写正确。

  2. “size + daily”并不是实时触发 轮转是否执行取决于 logrotate 的调度频率(cron 可能是每天一次)。 如果你希望“超过 100MB 很快就切”,需要把 logrotate 的执行频率提高(例如每小时跑一次),但这属于系统调度层面。

  3. copytruncate 的极小丢行风险 对绝大多数业务日志可接受;若你对日志完整性极端敏感,建议改成“程序支持 reopen + postrotate 发信号”的方式。


8. 最终可用配置

如果希望更“保守”(比如保留 7 份),只需调整一行:

rotate 7