Nginx日志切割,防止单个日志文件过大
Nginx 默认会把所有访问记录和错误信息写入同一个 access.log 和 error.log,时间一长文件可能涨到几个 GB,不仅占用磁盘,还会让排查问题变得困难。
如果你用的是小磁盘 VPS 或生产服务器,日志切割几乎是必做项。
本文按零基础能照做的节奏,讲清用 logrotate 自动切割、手动脚本切割以及宝塔面板操作三种方式,读完你可以选一种落地并验证效果。
先确认当前日志状态和切割需求
动手前建议先登录服务器,看一眼 Nginx 日志目录和文件大小,避免盲目操作。
# 查看 Nginx 主配置中日志路径,常见为 /var/log/nginx/
grep -r "access_log" /etc/nginx/nginx.conf
# 查看日志文件大小和数量
ls -lh /var/log/nginx/
如果发现 access.log 超过 500MB 或 error.log 超过 100MB,就值得做切割。
切割的核心逻辑是:把当前日志重命名归档,然后通知 Nginx 重新打开新日志文件写入,这样旧文件可以压缩、删除或长期保存,新文件从零开始。
方法一:用 logrotate 实现自动切割
logrotate 是 Linux 系统自带的日志轮转工具,大多数发行版已经安装。
Nginx 官方包通常会自动在 /etc/logrotate.d/nginx 生成配置,但有些环境需要手动添加。
检查或创建 logrotate 配置
cat /etc/logrotate.d/nginx
如果没有这个文件,用编辑器新建:
vim /etc/logrotate.d/nginx
写入以下内容(路径按你的实际日志目录调整):
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
关键参数解释:daily 表示每天切割一次;rotate 14 保留 14 份历史日志;compress 用 gzip 压缩旧日志;delaycompress 表示下一次切割时才压缩上一份,
避免影响正在写入的日志;postrotate 中的 kill -USR1 是通知 Nginx 重新打开日志文件的标准信号。
注意:create 0640 www-data adm 中的用户和组需要根据你的系统调整,Ubuntu/Debian 常用 www-data adm,CentOS 常用 nginx adm 或 root root。
不确定时可以先运行 ps aux | grep nginx 查看 Nginx 进程所属用户。
手动测试切割是否生效
配置写好后不要等第二天,直接用调试模式跑一次:
logrotate -d /etc/logrotate.d/nginx
-d 是 dry run,只显示会执行什么,不会真正切割。
确认输出没有报错后,强制立即执行一次:
logrotate -f /etc/logrotate.d/nginx
执行完再 ls -lh /var/log/nginx/,
应该能看到类似 access.log.1 或 access.log-20250101.gz 的归档文件,
同时新的 access.log 已经生成。
方法二:自定义脚本配合 crontab
如果服务器没有 logrotate 或者你想更灵活地控制切割时间,可以写一个简单脚本。
#!/bin/bash
LOG_DIR="/var/log/nginx"
DATE=$(date +%Y%m%d)
mv ${LOG_DIR}/access.log ${LOG_DIR}/access_${DATE}.log
mv ${LOG_DIR}/error.log ${LOG_DIR}/error_${DATE}.log
kill -USR1 $(cat /var/run/nginx.pid)
gzip ${LOG_DIR}/access_${DATE}.log
gzip ${LOG_DIR}/error_${DATE}.log
find ${LOG_DIR} -name "*.gz" -mtime +30 -delete
保存为 /usr/local/bin/nginx_log_rotate.sh,赋予执行权限:
chmod +x /usr/local/bin/nginx_log_rotate.sh
然后用 crontab -e 添加定时任务,每天凌晨 0 点执行:
0 0 * * * /usr/local/bin/nginx_log_rotate.sh
这个脚本会按日期重命名、
压缩,
并自动删除 30 天前的归档文件。注意:kill -USR1 的 PID 文件路径要确认正确,
有些编译安装的 Nginx 可能不在 /var/run/nginx.pid,
可用 nginx -t 或查看主配置中的 pid 指令。
方法三:宝塔面板图形化设置
如果你用的是宝塔面板,操作更直观。
登录面板后进入「网站」→「设置」→「日志」,或者直接点击左侧「日志」菜单。
找到 Nginx 日志切割选项,开启「日志切割」,设置切割周期(如每天)、保留份数(如 14 份)和是否压缩。
保存后宝塔会自动生成对应的 logrotate 规则。
验证方式:在宝塔「计划任务」中查看是否有日志切割任务,或者手动点击「执行」一次,然后到 /www/wwwlogs/ 目录(宝塔默认日志目录)查看是否出现按日期归档的文件。
常见报错和避坑提醒
- 切割后日志没有重新写入:多半是
postrotate里的kill -USR1没有生效,检查 Nginx PID 文件路径是否正确,或者 Nginx 是否以其他用户运行导致权限不足。 - 日志文件权限变成 root 导致 Nginx 无法写入:
create指定的用户和组必须与 Nginx 工作进程用户一致,否则新日志文件属主不对,Nginx 会报 Permission denied。 - logrotate 没有按预期每天执行:检查
/etc/cron.daily/logrotate是否存在且可执行,有些系统用 systemd timer 管理,可用systemctl status logrotate.timer查看。 - 磁盘还是被占满:切割后旧日志如果没压缩或保留份数太多,仍会占空间。建议开启
compress并把rotate设置为 7 到 30 之间,根据磁盘大小调整。
切割效果验证与后续维护
无论用哪种方法,切割后都要做一次完整验证:
- 执行一次切割操作,确认新日志文件已生成且 Nginx 正常写入。
- 访问网站几次,然后
tail -f /var/log/nginx/access.log,看是否有新记录写入。 - 检查归档文件是否按预期压缩或保留,例如
ls -lh /var/log/nginx/。 - 观察一两天,确认定时任务正常触发,磁盘占用没有持续增长。
如果发现切割后 Nginx 报错,优先用 nginx -t 检查配置,再查看 error.log 中的具体信息。
养成定期检查日志目录的习惯,比等到磁盘告警再处理要省事得多。