服务器日志轮转 logrotate 如何配置

juming
juming 初级会员超兽战士
发布于 2026-10-08 10:18 ·2 浏览 ·0 回复

学完这篇,你能独立给服务器上任意一个服务(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 是否在跑。
版权声明:本文来自 GJ站长论坛《服务器日志轮转 logrotate 如何配置》
原文链接:https://www.gj0.com/thread-895.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~