摘要
logrotate 配置存在但日志持续增长的 7 个检查点:执行状态与 status 记账、
size与daily的优先级、配置文件权限被忽略、同一路径被多份配置覆盖、nginx 需发 USR1 重开文件、dateext撞名静默跳过、已删除文件仍占用空间。含配置模板、-d/-f验证流程与容量估算方法。
现象与环境
/etc/logrotate.d/ 下已有对应配置,日志文件仍持续增长,df -h 显示分区使用率上升。
环境:Ubuntu 22.04(logrotate 3.19)、CentOS 7(logrotate 3.8)、nginx 1.20+、systemd。路径与用户需按实际替换。
1. 判定分层
|
现象 |
结论方向 |
检查点 |
|
|
未被匹配 / 被跳过 |
① ③ ④ |
|
|
触发了但没转成 |
⑤ ⑥ |
|
转了但空间不减 |
进程仍持有旧 inode |
⑤ ⑦ |
2. 七个检查点
① 执行状态
systemctl list-timers --all | grep -i logrotate
journalctl -u logrotate --since "-7 days" --no-pager | tail -20
tail -5 /var/lib/logrotate/status
status 每行格式为「路径 上次轮转的日期」,日期停滞即未处理。
② size 与 daily 的优先级
|
指令 |
语义 |
|
|
每天一次,不看大小 |
|
|
只看大小,时间条件失效 |
|
|
时间到且大于 N 才转 |
size 与 daily 并存时 size 生效,daily 被忽略。
③ 配置文件权限
ls -l /etc/logrotate.d/
# 要求 -rw-r--r-- 属主 root;组或其他可写会被忽略
④ 同一路径被多份配置覆盖
grep -rn "access.log" /etc/logrotate.d /etc/logrotate.conf
后读到的配置覆盖先读到的,不合并。include 按文件名顺序读取。
⑤ nginx 日志需信号重开
ls -l /proc/$(cat /run/nginx.pid)/fd | grep log
指向 *.log.1 或带 (deleted) 即为未重开,需 postrotate 发 USR1。
⑥ dateext 撞名
同日重复 -f 时目标文件已存在,静默跳过,不报错。
⑦ 已删除文件占用
lsof +L1 | grep -i log
3. 配置模板
/var/log/nginx/*.log {
daily
minsize 50M
rotate 14
maxage 30
missingok
notifempty
compress
delaycompress
sharedscripts
create 0640 www-data adm
postrotate
[ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}
要点:minsize 而非 size(保留时间语义);create 显式指定属主,避免轮转后写不进;sharedscripts 让多个日志只发一次信号。
4. 验证流程
logrotate -d /etc/logrotate.conf # 空跑,只看解析结果
logrotate -f /etc/logrotate.d/nginx # 强制一次
ls -l /var/log/nginx/ # 属主与权限
df -h /var # 空间是否释放
tail -3 /var/lib/logrotate/status # 记账是否更新
5. 容量估算
du -sh /var/log/nginx
awk '{print $10}' /var/log/nginx/access.log | sort -u | wc -l # 独立 IP 量级参考
日增量 × 保留天数 × 压缩比(文本约 1/10),再乘 2 作为峰值余量。
6. 多机场景的观察方式
四台机器各自配好之后,真正难的是「哪台的配额快到了」这件事没人主动看。逐台登进去 du 一遍太慢,通常的做法是装采集端统一上报。
7. 另一条观察路径
如果不愿在每台机器上装采集端,可以只走 SSH:不装采集 agent,直接读日志目录大小、inode 占用和 status 文件,这类「无 agent 监控」的界面在本地渲染、只走现成的 SSH 通道,服务器侧不装 Web 服务、也不新增端口。
我在四台 VPS 上用极目Linux桌面看这些读数,省得一台台进目录翻;规则写错没有它也不管,那部分只能自己看 -d。
无论哪种方式,选型时建议固定一条:看它是否在服务器上新增对外端口。 新增的端口就是长期要盯的资产。
8. FAQ
Q1:missingok 和 notifempty 能同时写吗?
能,而且经常一起写。missingok 是文件不存在时不报错、静默跳过;notifempty 是文件为空时不轮转。两者语义不冲突:前者管「没有这个文件」,后者管「有这个文件但没内容」。都写上可以避免日志被清理后留下大量报错。
Q2:sharedscripts 是干什么的?
让 prerotate/postrotate 在一批日志处理完后只执行一次,而不是每转一个文件执行一次。nginx、apache 这类一个信号就能重开全部日志的进程必须加,否则 N 个日志就发 N 次信号,日志多的时候会看到明显的服务抖动。只有一两个日志文件的站点,加不加差别不大,没必要为它改配置。
Q3:su 指令什么时候必须写?
当配置文件的属主不是 root、或日志文件属于非 root 用户、而 logrotate 又以 root 身份运行时。不写会报 parent directory has insecure permissions 或直接跳过。写法是 su www-data adm,指定以哪个用户和组去操作文件。
Q4:dateext 生成的旧文件怎么自动清理?
靠 rotate 或 maxage,不是靠文件名。rotate 按份数删最老的,maxage 按天数删。如果用了自定义 dateformat(比如带小时),份数和天数的对应关系会变,需要重新算 rotate 的值,否则保留期会比预期短很多。
Q5:logrotate 能改成每小时跑一次吗?
能。改触发方式就行:不用 cron.daily,在 /etc/cron.d/ 里加一条 0 * * * * root /usr/sbin/logrotate /etc/logrotate.conf,配置里用 hourly 或 size。注意 hourly 在老版本(3.8 以前)不支持,CentOS 7 上得靠 size 或 minsize 控制。
Q6:日志 500MB/天,单机 logrotate 撑得住吗?
撑得住,但要看压缩开销。500MB 文本 gzip 大约需要几秒到十几秒的单核时间,一天一次可以忽略;如果拆成每小时一次,压缩会和业务抢 CPU,建议错开到凌晨或改用 delaycompress 错峰。真正撑不住的是「一天几 G + 只留 30 天」这种组合,那是容量规划问题,不是轮转问题。
Q7:logrotate -f 成功但文件没变,为什么?
三种可能:dateext 目标文件已存在被跳过;配置里 notifempty 而文件为空;-f 指定的路径不是实际生效的那份配置(被另一份覆盖了)。先看 -d 的输出里这条日志有没有被列出,再判断属于哪一种。
Q8:/etc/logrotate.d/ 下的文件名能带扩展名吗?
能,但没必要,而且有坑。logrotate 会跳过 tabooext 列表里的后缀(.rpmnew、.rpmsave、.rpmorig、.dpkg-old、.dpkg-dist 等),带这些后缀的配置不会被执行。用 nginx 这种无后缀命名最稳,也便于 grep 定位。
532



被折叠的 条评论
为什么被折叠?



