最稳妥的 nginx 日志轮转方案是用 logrotate 配合 usr1 信号:配置须放 /etc/logrotate.d/nginx(权限 644),路径、dateyesterday、sharedscripts 和 postrotate 中安全获取 pid 并 kill -usr1 缺一不可,上线前必须用 -d 和 -vf 手动验证。

直接用 logrotate 配合 Nginx 是最稳妥、最通用的做法。关键不是“能不能切”,而是配置路径、信号通知和时间语义是否准确——错一处,日志就可能堆积或中断写入。
配置文件必须放在 /etc/logrotate.d/nginx
logrotate 默认只扫描 /etc/logrotate.d/ 目录下的文件,每天由 /etc/cron.daily/logrotate 自动触发。放错位置(比如 /root/nginx.logrotate 或加了 .conf 后缀)会导致 cron 完全忽略它。
- 用
sudo tee /etc/logrotate.d/nginx写入,确保权限为644,属主属组是root:root - 不要修改
/etc/logrotate.conf主文件——系统更新时容易被覆盖,也不利于服务隔离 - 确认 Nginx 日志路径与配置中一致,例如:
/var/log/nginx/*.log或/usr/local/nginx/logs/*.log
按天归档需启用 dateext + dateyesterday
仅写 daily 和 dateext,生成的文件名是 access.log-2026-06-17(轮转当天日期),但实际你想存的是“昨天的日志”。加 dateyesterday 才会让文件名显示为 access.log-2026-06-16,语义更清晰。
-
dateformat -%Y-%m-%d要配合dateext使用,否则无效 - 如果同时设了
size 100M和daily,大小优先:达到阈值立即轮转,不等午夜 - 建议搭配
notifempty,避免空日志也被轮转产生冗余文件
postrotate 必须用 kill -USR1,且安全获取 PID
Nginx 收到 USR1 信号后会原子性地重新打开日志文件句柄,不中断请求;而 systemctl reload 或 nginx -s reload 会触发 worker 进程平滑重启,有丢请求风险,且依赖 systemd 环境(部分容器或 OpenRC 系统无 systemctl)。
- 推荐写法:
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") - 务必加上
sharedscripts,避免多个日志文件(如 access.log、error.log)触发多次 USR1
验证与调试不能跳过
上线前必须手动测试,否则 cron 执行失败你根本不会立刻发现。
- 先用
logrotate -d /etc/logrotate.d/nginx查看模拟执行流程,检查路径、权限、PID 是否可读 - 再用
logrotate -vf /etc/logrotate.d/nginx强制执行一次,观察/var/log/nginx/下是否生成带日期后缀的新归档文件 - 检查新
access.log是否有新写入内容(tail -f),确认 Nginx 仍在正常记录











