一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

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 —— 这会中断连接,且和日志切割无关

dateextdateformat 必须配合 dailyhourly 才生效

只加 dateext 不够:logrotate 默认用数字后缀(access.log.1access.log.2),加了 dateext 才会变成 access.log-2026-04-26。但如果你同时写了 dailydateformat %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.logerror.logproxy.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 还在往旧文件写。

热门栏目