Nginx日志切割自动归档配置从零开始
为什么要做 Nginx 日志切割与归档
Nginx 默认会把所有访问日志写到同一个文件(如 access.log),时间一长这个文件会变得非常大,不仅占用磁盘,还会拖慢日志查询速度。
通过日志切割自动归档,我们可以按天(或小时)把旧日志切分成小文件并压缩存储,同时让 Nginx 继续写入新文件。
整个过程可以完全自动化,无需人工干预。
配置前的准备
在动手之前,你需要确认以下几点:
- Nginx 已正确安装,且知道日志存放目录(通常是
/var/log/nginx/)。 - 服务器系统:本文以 CentOS 7 / Ubuntu 20.04 为例,命令几乎通用。
- 拥有 root 或 sudo 权限,因为要修改系统计划任务和日志文件。
查看当前日志位置的方法:
# 查看 Nginx 主配置中的日志路径
grep -E 'access_log|error_log' /etc/nginx/nginx.conf
如果 Nginx 配置里没有写绝对路径,默认日志在 /var/log/nginx/ 下。
使用 logrotate 自动切割 Nginx 日志
系统自带的 logrotate 工具是完成这项工作的首选,配置简单且稳定。
第一步:创建 logrotate 配置文件
在 /etc/logrotate.d/ 目录下新建一个名为 nginx 的文件:
sudo vim /etc/logrotate.d/nginx
粘贴以下内容(请根据你的实际日志路径和需求调整):
/var/log/nginx/*.log {
daily # 每天轮转一次
missingok # 如果日志文件丢失则跳过,不报错
rotate 30 # 保留最近 30 个归档文件
compress # 压缩归档文件(gzip)
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
}
关键说明:
create的属主和属组要与你的 Nginx 工作进程一致。如果 Nginx 以nginx用户运行,改为create 0640 nginx adm。postrotate里的kill -USR1是平滑通知 Nginx 重新打开日志文件,不会中断服务。
第二步:测试配置并手动执行一次
# 测试配置语法
debug logrotate -d /etc/logrotate.d/nginx
# 强制立即执行一次轮转(不等待定时任务)
sudo logrotate -f /etc/logrotate.d/nginx
如果输出没有报错,检查 /var/log/nginx/ 目录,你应该能看到类似 access.log-20250410.gz 的归档文件。
第三步:确认定时任务已启用
logrotate 默认由 cron 每天执行一次,一般配置在 /etc/cron.daily/logrotate 里。
你可以手动运行这个脚本或者直接检查:
ls -l /etc/cron.daily/logrotate
如果需要按小时切割,可以使用 hourly 并放入 /etc/cron.hourly/ 目录,但日常使用 daily 已足够。
手动切割脚本(备选方案)
如果 logrotate 不满足你的定制需求,也可以自己写一个 Shell 脚本配合 crontab:
#!/bin/bash
# /usr/local/bin/nginx-logrotate.sh
LOG_DIR="/var/log/nginx"
YESTERDAY=$(date -d "yesterday" +"%Y%m%d")
cd $LOG_DIR
for log in *.log; do
[ -f "$log" ] || continue
mv "$log" "${log}.${YESTERDAY}"
done
gzip *.log.* 2>/dev/null
kill -USR1 $(cat /var/run/nginx.pid)
赋予执行权限,并添加 crontab:
chmod +x /usr/local/bin/nginx-logrotate.sh
crontab -e
# 每天凌晨 0 点执行
0 0 * * * /usr/local/bin/nginx-logrotate.sh
效果验证与常见问题
验证步骤
- 执行轮转后,访问站点生成一些日志。
- 查看日志目录:
ls -lh /var/log/nginx/,确认有新生成的access.log和打包的旧文件。 - 检查 Nginx 是否正常:
curl -I http://localhost或查看error.log有无异常。
高频问题
Q:轮转后 Nginx 还在往旧文件写日志?
A:通常是因为 postrotate 中的 kill -USR1 没有生效。
检查 Nginx PID 文件路径是否正确,或者手动执行 sudo nginx -s reopen 替代。
Q:新日志文件属主错误导致无法写入?
A:确认 create 指令中的用户和组与 Nginx 运行用户一致。
可以用 ps aux | grep nginx 查看 worker 进程的用户。
Q:日志文件没有压缩?
A:检查 compress 和 delaycompress 是否同时使用。
如果 delaycompress 开启,上一轮的文件会在下一轮才压缩,属于正常行为。
避坑要点
- 不要手动删除日志文件,使用 logrotate 自动管理,避免 Nginx 句柄失效。
- 日志目录磁盘空间监控:建议配合
df -h或告警工具,防止日志暴增撑爆磁盘。 - 配置修改后先
debug测试,避免生产环境直接跑出问题。
总结
通过 logrotate 或脚本 + crontab,你可以轻松实现 Nginx 日志切割自动归档。
推荐优先使用 logrotate,因为它更成熟、配置声明式,且与系统日志管理无缝集成。
按照本文步骤,从准备到验证,一个小时内就能搞定。
后续遇到异常时,优先检查 postrotate 执行状态和文件权限,大部分问题都能快速定位。