服务器日志轮转 logrotate 如何配置
学完这篇,你能独立给服务器上任意一个服务(Nginx、Tomcat、自研程序)写好 logrotate 配置,让它每天自动切割、压缩、清理日志,不再出现日志撑爆磁盘的事故。
第一步:认清 logrotate 的两个入口文件
这一步的目标是知道配置该写在哪、全局规则是什么。logrotate 的所有配置分两层:
- 主配置:
/etc/logrotate.conf,定义全局默认值(默认weekly、rotate 4、create)。 - 子配置目录:
/etc/logrotate.d/,每个服务一个文件,主配置里用include /etc/logrotate.d把它们全部加载进来。
先看一遍主配置内容:
cat /etc/logrotate.conf
注意:不要直接改主配置来管单个应用,写在
/etc/logrotate.d/下单独文件更清晰,升级软件包时也不会互相覆盖。
第二步:确认 logrotate 装没装、按什么节奏跑
这一步要确认程序存在、并且知道是谁在定时调用它。
logrotate --version # CentOS 7 一般是 3.8.6,Ubuntu 20.04 是 3.14.0
再看调度方式,两种常见:
ls /etc/cron.daily/logrotate # CentOS / Debian 老方式,每天跑一次
systemctl list-timers | grep logrotate # systemd 系统,由 logrotate.timer 触发
没装就 yum install logrotate 或 apt install logrotate。
注意:
/etc/cron.daily/logrotate是由 crond 触发的,如果服务器 crond 没启动(systemctl status crond),配置写得再对也不会执行。
第三步:写一份可用的配置
目标:为 /var/log/myapp/app.log 写一份每天轮转、保留 7 天、压缩归档的配置。新建 /etc/logrotate.d/myapp:
/var/log/myapp/app.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
dateext
dateformat -%Y%m%d
create 0640 www-data adm
su www-data adm
postrotate
/usr/bin/systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
关键参数含义:
| 参数 | 作用 |
|---|---|
daily | 每天轮转(也可写 weekly、size 100M) |
rotate 7 | 最多保留 7 个历史文件,第 8 个被删除 |
missingok | 文件不存在时不报错 |
notifempty | 文件为空时不轮转 |
delaycompress | 延迟一轮再压缩,避免程序还握着旧文件 |
dateext | 用日期做后缀,如 app.log-20240521 |
create 0640 www-data adm | 轮转后新建文件的权限和属主 |
su www-data adm | 以指定用户身份执行轮转,解决目录权限问题 |
postrotate ... endscript | 轮转后执行的命令,通常让程序重新打开日志文件 |
注意:
postrotate里的命令一定要加> /dev/null 2>&1 || true。脚本返回非 0 会让 logrotate 报错并中断整个执行流程。
第四步:先调试,再真正执行
这一步是不产生任何实际影响的验证,务必先做。
logrotate -d /etc/logrotate.d/myapp
-d(debug)只打印它会做什么,不移动文件。确认输出的 rotating pattern 和 considering log 都是你期望的文件后,再强制跑一次:
logrotate -vf /etc/logrotate.d/myapp
-v 详细输出,-f 忽略时间条件强制轮转。跑完去 ls -l /var/log/myapp/ 看是否生成了 app.log-20240521.gz。
注意:如果你在测试时改了系统时间,发现不轮转,去看状态文件
/var/lib/logrotate/logrotate.status——它记录了每个日志上次轮转的日期,可临时用logrotate -s /tmp/lr.state -f 配置指定新状态文件绕过。
第五步:处理「程序不重新打开日志」的坑
如果程序不支持 reload,轮转后它仍写向已被重命名的旧文件,新文件永远是空的。两种解法:
- 支持信号:写成
postrotate kill -USR1 $(cat /var/run/myapp.pid) endscript。 - 完全不支持:把
create系列换成copytruncate,即先复制再清空原文件。
/var/log/myapp/app.log {
daily
rotate 7
copytruncate
compress
missingok
notifempty
}
注意:
copytruncate在复制与清空之间有一个极短窗口,期间的写入可能丢失,所以能用 reload/信号就优先用信号方式。另外copytruncate与create不要同时写。
小结
- 配置写在
/etc/logrotate.d/下一个服务一个文件,别改主配置。 - 核心参数:
daily/size定频率,rotate N定保留数,compress + delaycompress定压缩,create定新文件权限。 - 必须用
logrotate -d预演、logrotate -vf实测,再交给 cron 或 systemd timer。 - 程序能 reload 就用
postrotate+ 信号;不能就用copytruncate,并接受极小的丢日志风险。 - 排查看
/var/lib/logrotate/logrotate.status,执行者看crond或logrotate.timer是否在跑。
原文链接:https://www.gj0.com/thread-895.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。