最稳妥的方案是配合系统自带的 logrotate 工具,搭配 Nginx 信号通知,实现自动切割与归档。
先说结论:生产环境建议直接使用 logrotate 管理,不要自己写脚本轮询
- 适合:绝大多数基于 Linux 的 Nginx 部署场景
- 先准备:确认 logrotate 已安装且拥有日志文件写入权限
- 关键检查:务必确认 Nginx 运行用户组及 PID 文件路径,避免权限错误或信号发送失败
- 验收:检查切割后的旧日志是否压缩,新日志是否能正常写入
前置检查:确认用户与 PID 路径
不同 Linux 发行版默认用户不同,直接复制配置可能导致权限错误。执行以下命令确认实际环境:
1. 确认 Nginx 运行用户
ps -ef | grep nginx | grep -v grep
观察第一列用户名的列,CentOS/RHEL 通常为 nginx,Ubuntu/Debian 通常为 www-data。
2. 确认 PID 文件路径
查看 nginx.conf 配置中的 pid 指令,或使用以下命令查找:
nginx -t 2>&1 | grep pid
常见路径为 /var/run/nginx.pid 或 /run/nginx.pid,若自定义过路径,需以实际配置为准。
配置 logrotate 规则
在 /etc/logrotate.d/ 目录下新建 nginx 配置文件,内容参考如下。注意修改 create 行的用户组和 postrotate 中的 PID 路径。
cat > /etc/logrotate.d/nginx <<EOF
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 <用户> <用户组> # 例如:nginx nginx 或 www-data www-data
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then # 请根据前置检查修改此路径
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
EOF
原理简述
Nginx 默认不会主动切割日志文件。logrotate 按时间或大小切割后,通过 postrotate 脚本发送 USR1 信号通知 Nginx 重新打开日志文件句柄。若不发送信号,Nginx 会继续往旧文件句柄写入,导致切割失效。
验证是否生效
1. 手动触发测试
logrotate -f /etc/logrotate.d/nginx
2. 查看文件列表
ls -lh /var/log/nginx/
确认是否生成了带时间戳或序号的旧日志文件,且后缀包含 .gz(若有 compress)。
3. 检查新日志写入
访问一次网站,然后执行 tail -f /var/log/nginx/access.log 确认新的请求是否记录在当前文件中。
常见坑与排查
1. 权限不足(Permission denied)
现象:logrotate 报错或新日志文件无法写入。
解决:确保 create 参数中的用户组与 Nginx 运行用户一致。若 Nginx 以 root 启动 worker,通常仍需指定为普通用户以防安全风险,但需确保该用户有写权限。
2. 信号发送失败
现象:日志切割后,新请求仍写入旧文件。
解决:检查 postrotate 中的 PID 文件路径是否与 nginx.conf 中一致。若路径错误,Nginx 收不到 USR1 信号。
3. 压缩占用 CPU
现象:切割瞬间 CPU 飙升。
解决:日志量极大时,可关闭 compress 或改用 delaycompress 延迟到下一次切割时再压缩。
4. 保留周期过长
建议根据磁盘容量调整 rotate 数字,未压缩的日志占用空间较大。