最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Linux如何配置Nginx日志自动切分 Linux下Logrotate工具详解
时间:2026-06-16 08:06:14 编辑:袖梨 来源:一聚教程网
logrotate 配置必须放在 /etc/logrotate.d/ 才能被 cron 自动执行;应单独为每个日志文件配置、避免通配符,使用 dateext dateyesterday dateformat -%Y-%m-%d 实现按天归档,并在 postrotate 中用 kill -USR1 安全重载 Nginx。
logrotate 配置文件必须放在 /etc/logrotate.d/ 才会被自动加载
系统默认通过 /etc/cron.daily/logrotate 每天执行一次,而这个脚本会读取 /etc/logrotate.conf,里面有一行 include /etc/logrotate.d —— 这意味着只有放在这里的配置才会被识别。直接改 /etc/logrotate.conf 主文件虽然也能生效,但不推荐:它容易被系统更新覆盖,且不符合服务隔离原则。
常见错误是把 nginx 配置写在别的路径(比如 /root/nginx.logrotate),然后手动运行 logrotate -f 测试成功,就以为部署好了——其实 cron 永远不会执行它。
- 正确做法:用
sudo tee /etc/logrotate.d/nginx写入配置 - 确认权限为
644,属主属组为root:root - 不要给配置文件加
.conf后缀,logrotate 只认文件名本身(如nginx)
postrotate 里用 kill -USR1 而不是 systemctl reload
Nginx 收到 USR1 信号后会重新打开日志文件句柄,这是原子操作、零停机;而 systemctl reload 会触发 worker 进程平滑重启,可能丢请求,还依赖 systemd 环境(比如某些精简版容器或 OpenRC 系统根本没 systemctl)。
关键点在于获取 master 进程 PID:不能硬编码路径,要优先查 pid 配置项。如果 Nginx 启动时没指定 pid,默认是 /var/run/nginx.pid 或 /usr/local/nginx/logs/nginx.pid,得根据实际安装路径判断。
- 安全写法:
if [ -f /var/run/nginx.pid ]; then kill -USR1 $(cat /var/run/nginx.pid); fi - 更健壮的写法(兼容多路径):
pidfile=$(nginx -t 2>&1 | grep "pid" | awk '{print $NF}'); [ -f "$pidfile" ] && kill -USR1 $(cat "$pidfile") - 避免在
postrotate里写systemctl restart nginx—— 这会中断连接,且和日志切割无关
dateext 和 dateformat 必须配合 daily 或 hourly 才生效
只加 dateext 不够:logrotate 默认用数字后缀(access.log.1、access.log.2),加了 dateext 才会变成 access.log-2026-04-26。但如果你同时写了 daily 和 dateformat %Y-%m-%d,它生成的日期是“轮转发生当天”的日期;而加 dateyesterday 才会让文件名显示昨天的日期(更符合“按天归档”的语义)。
注意:dateformat 的格式字符串必须用 % 开头,且不能包含空格或非法字符,否则 logrotate 直接报错退出,整条配置失效。
- 推荐组合:
daily dateext dateyesterday dateformat -%Y-%m-%d - 错误示例:
dateformat "_%Y_%m_%d"(下划线开头会导致文件名解析失败) - 测试是否生效:手动运行
sudo logrotate -vf /etc/logrotate.d/nginx,看新文件名是否含日期
日志路径通配符要小心 * 匹配范围
配置里写 /var/log/nginx/*.log 看似方便,但如果有 access.log、error.log、proxy.log,logrotate 会把它们当做一个组来处理——rotate 数、compress、postrotate 全部共用一套逻辑。这通常不是你想要的:比如 error.log 很小,不该和 access.log 一起压缩;或者你只想对 access.log 做 dateext,error.log 保持数字后缀。
更稳妥的做法是为每个日志文件单独写一段配置块,用注释区分开。这样各管各的,互不干扰。
- 错误写法:
/var/log/nginx/*.log { daily rotate 7 ... } - 正确写法:分别写两段,各自指定完整路径
- 路径中含变量(如
$HOME)或 shell 表达式(如$(date))会被忽略——logrotate 不解析 shell
真正麻烦的是 postrotate 里调用外部命令失败却无提示:logrotate 默认静默忽略错误,除非加 -v 参数。所以第一次部署后务必手动跑一次 logrotate -vf,盯着输出看有没有 “error” 或 “skipping” 字样。否则你以为切分正常,其实 postrotate 根本没执行成功,Nginx 还在往旧文件写。