Nginx日志切割从入门到实战:自动轮转与排错全攻略
为什么需要 Nginx 日志切割
Nginx 默认把所有访问记录和错误信息写入一个文件,比如 access.log 和 error.log。
时间一长,单文件可能膨胀到几个 GB,不仅拖慢日志查看速度,还容易占满磁盘分区导致服务异常。
日志切割就是按时间(每天)或按大小把大文件切分成小段,并删除过期旧日志,让磁盘空间和日志可读性都保持健康。
准备工作:确认环境与权限
开始操作前,先检查三样东西:
- 系统是否带 logrotate:执行
which logrotate,如果返回路径(如/usr/sbin/logrotate)说明已安装;没有的话用apt install logrotate(Debian/Ubuntu)或yum install logrotate(CentOS)。 - Nginx 进程用户:通常为
www-data或nginx,用ps aux | grep nginx确认主进程是 root 运行,worker 进程以低权限用户运行。 - 日志目录权限:确保运行 logrotate 的用户(通常是 root)对
/var/log/nginx/有读写权限。
方法一:使用 logrotate 自动切割(推荐)
logrotate 是 Linux 系统自带的日志轮转工具,配置好后每天自动运行。
第一步:创建 logrotate 配置
执行以下命令新建配置文件:
sudo vi /etc/logrotate.d/nginx
填入以下内容(按实际情况调整路径):
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
配置项说明:
daily:每天切割一次。rotate 30:保留最近 30 个归档文件。compress:用 gzip 压缩旧日志。postrotate块:切割后向 Nginx 主进程发送 USR1 信号,让它重新打开日志文件,否则 Nginx 会继续往已切走的文件里写。
第二步:测试配置是否正确
sudo logrotate -d /etc/logrotate.d/nginx
-d 是调试模式,只模拟执行,不实际切割。
如果输出没有报错,说明配置语法没问题。
第三步:立即执行一次切割
sudo logrotate -f /etc/logrotate.d/nginx
-f 强制轮转,会立即生成归档文件(如 access.log.1.gz)。
方法二:使用 Shell 脚本 + crontab 实现手动切割
如果服务器无法安装 logrotate,或者想更灵活控制切割策略,可以写脚本配合定时任务。
创建一个切割脚本
sudo vi /usr/local/bin/nginx-logrotate.sh
内容:
#!/bin/bash
LOG_DIR=/var/log/nginx
YESTERDAY=$(date -d "yesterday" +%Y%m%d)
for log in access.log error.log; do
if [ -f "$LOG_DIR/$log" ]; then
mv "$LOG_DIR/$log" "$LOG_DIR/${log}.${YESTERDAY}"
gzip "$LOG_DIR/${log}.${YESTERDAY}"
fi
done
# 通知 Nginx 重新打开日志文件
kill -USR1 $(cat /var/run/nginx.pid)
# 删除 30 天前的旧日志
find $LOG_DIR -name "*.gz" -mtime +30 -delete
赋予执行权限:sudo chmod +x /usr/local/bin/nginx-logrotate.sh
添加到 crontab
sudo crontab -e
添加一行,每天凌晨 0:01 执行:
1 0 * * * /usr/local/bin/nginx-logrotate.sh >/dev/null 2>&1
常见问题与避坑指南
问题1:切割后 Nginx 继续往旧文件写日志?
原因:没有发送 USR1 信号。
logrotate 配置中的 postrotate 或脚本中的 kill -USR1 必须正确写入。
验证方法:切割后执行 ls -lh /var/log/nginx/,如果最新日志的修改时间仍然是旧时间,说明信号没发成功。
问题2:日志文件权限变成 root 导致 Nginx 无法写入?
解决办法:logrotate 配置中加上 create 0640 www-data adm,让新日志文件继承正确的用户和组。
如果使用脚本,可以在 mv 后加一句 chown www-data:adm $newfile。
问题3:切割后日志丢失?
检查点:rotate 数值设置过小(如 7),导致旧日志被过早删除。
建议根据磁盘空间至少保留 30 天。
另外确认 missingok 已启用,避免因某个日志不存在而中断。
效果验证步骤
- 检查切割出的归档文件:
ls -lh /var/log/nginx/
应当看到类似 access.log.20250328.gz 的压缩文件,且当前 access.log 文件大小很小。
- 确认 Nginx 仍在正常写入:刷新你的网站页面,然后查看
access.log的 mtime 是否更新。 - 查看系统 logrotate 执行记录(如果使用 logrotate):
cat /var/log/logrotate/logrotate.status | grep nginx
至此,你的 Nginx 日志切割方案已部署完成。
建议隔天再检查一次归档文件是否正常生成,之后每月看一眼磁盘水位即可。
遇到其他异常,优先回顾本文的「避坑指南」部分。