必须用 logrotate 管理 Nginx 日志,因其不中断服务、不丢日志;需发 USR1 信号通知 Nginx 重开日志文件,HUP 仅重载配置,TERM/INT 会终止进程;配置须含 dateext、delaycompress、create 等关键参数并匹配运行用户权限。

直接用 logrotate,别自己写脚本。它不中断服务、不丢日志、配置一次就自动跑,99% 的生产环境都这么干。
为什么必须发 USR1 信号而不是重启或 HUP
Nginx 工作进程靠文件描述符写日志,不是靠文件名。你直接 mv access.log access.log-20260907,它还在往旧文件里写——直到你通知它“该换新文件了”。kill -USR1 是唯一能触发它按配置中 access_log 路径重新打开新文件的信号。HUP 只重载配置,TERM/INT 会终止进程,都不管日志切换。
-
USR1是 Nginx 官方文档明确指定的日志 reopen 信号,不能替换成别的 - 如果
/var/run/nginx.pid不存在,先确认 Nginx 进程是否真在运行:ps aux | grep nginx,再找对 pid 文件路径(比如/usr/local/nginx/logs/nginx.pid) - 权限不对会导致
postrotate脚本里的kill命令失败,检查logrotate运行用户(通常是root)是否有权读取 pid 文件
logrotate 配置里这几个参数不能乱设
下面这段是核心,少一个都可能出问题:
/var/log/nginx/*.log {
daily
rotate 30
dateext
dateformat -%Y%m%d
compress
delaycompress
missingok
notifempty
create 0640 nginx nginx
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 $(cat /var/run/nginx.pid)
fi
endscript
}
-
dateext+dateformat必须一起用,否则后缀是-YYYYMMDD(默认)或乱码,不方便按日期筛选 -
delaycompress很关键:保留最新一份未压缩日志,方便排查刚发生的问题;没有它,昨天的日志一生成就被压成.gz,查起来多一层解压 -
create 0640 nginx nginx中的用户组要和 Nginx 实际运行用户一致,CentOS 常是nginx,Ubuntu/Debian 一般是www-data,错一个,新日志文件权限不对,Nginx 写不进去
测试配置前先验证三件事
别等 cron 自动跑才发现配错了。手动执行前确认:
- 目标日志路径真实存在且可读:
ls -l /var/log/nginx/*.log,如果路径是/usr/local/nginx/logs/,就改配置里第一行 - pid 文件路径准确:
cat /proc/$(pgrep nginx | head -1)/cmdline | tr '\0' '\n' | grep -E "(pid|conf)"能帮你定位实际配置中pid指令写的路径 - 用
logrotate -d /etc/logrotate.d/nginx看 debug 输出,重点扫一眼有没有error:或warning:行,比如error: error creating output file就是权限问题
真正容易被忽略的是:logrotate 默认每天凌晨执行,但它的触发依赖系统级 cron(/etc/cron.daily/logrotate),而有些容器化或最小化安装的系统压根没开 anacron 或 cron 服务。跑完 logrotate -f 看效果后,务必用 systemctl status cron 或 service crond status 确认定时任务守护进程是 active 的。


















