服务器跑久了,/var/log/nginx/ 里的 access.log 和 error.log 会越来越大——一个日访问量上万的小站,日志几个月就能涨到几个 GB,把磁盘塞满,网站直接出错。日志必须定期"切分"(轮转):按天或按大小把当前日志分成一个个小文件,压缩旧的、保留一定时间后删除。这篇文章教你怎么用 logrotate 对 Nginx 日志做自动切割与清理。
一、为什么要做日志切割
Nginx 默认把所有访问日志写进同一个文件,越积越大,带来三个问题:
- 磁盘占满:日志无限增长,最终撑爆磁盘
- 排查困难:几 GB 一个文件,grep 一次慢得不行
- 性能影响:日志文件太大会拖慢 Nginx 写入
日志切割后用 daily(按天)分文件、压缩历史、定期清理,既节省磁盘又方便排查。
二、认识 logrotate
Linux 自带的 logrotate 就是做日志轮转的:按周期把日志改名、启动新的空日志、对旧日志压缩和清理。它的配置文件分两类:
- 主配置:
/etc/logrotate.conf - 软件各自的规则:
/etc/logrotate.d/(推荐在这里加 Nginx 规则)
三、检查 Nginx 日志位置
先确认日志在哪:
# 查看 Nginx 配置里的日志路径
grep -rE 'access_log|error_log' /etc/nginx/ 2>/dev/null
宝塔面板站点日志一般在 /www/wwwlogs/,包路径随意,规则里写到你的实际路径即可。
四、为 Nginx 配置日志切割
创建一个规则文件 /etc/logrotate.d/nginx:
/var/log/nginx/*.log {
daily # 每天切割一次(也可 weekly)
rotate 30 # 保留 30 份(即 30 天)
compress # 旧日志压缩成 .gz
delaycompress # 本轮结束后再压缩,便于刚切割时还能查昨天的
missingok # 日志不存在也不报错
notifempty # 日志为空不轮转
create 0640 www-data adm # 新的日志文件权限
sharedscripts
postrotate
# 通知 Nginx 重新打开日志文件,否则日志会继续写进旧文件
if [ -f /run/nginx.pid ]; then
kill -USR1 `cat /run/nginx.pid`
fi
endscript
}
把 /var/log/nginx/*.log 换成你实际的日志目录。如果是宝塔面板,改为 /www/wwwlogs/*.log。
关键点:postrotate 里的 kill -USR1 很关键。Nginx 运行时会一直握着旧日志文件句柄,切割后必须通知它重新打开新文件,否则旧文件还在被写入,切割就失效了。
测试规则是否正确:
logrotate -d /etc/logrotate.d/nginx # -d 试运行,打印执行计划但不真正执行
手动执行一次:
logrotate -f /etc/logrotate.d/nginx # -f 强制执行
五、验证切割结果
执行后查看日志目录:
ls -lh /var/log/nginx/
# access.log <- 当前正在写的
# access.log.1.gz 或 access.log.1 <- 昨天的,已压缩
# access.log.2.gz <- 前天的
日志被按时切成独立小文件,并且旧文件已压缩,磁盘占用大幅下降。
六、Nginx 错误日志清理专项
除了访问日志,error.log 也可能异常增长(如被刷 404、反复报错)。可以单独设一条规则,或结合本站磁盘清理与 Nginx 限流教程从源头减少报错。
临时手动清空(仅应急):
> /var/log/nginx/error.log # 用 : > 或 truncate 清空,而不是 rm
定期清理超过一定大小的免费方案可参考上面 rotate + maxsize:
maxsize 200M # 在规则中加上,超过 200M 即使没到周期也会切割
七、宝塔面板 / 其他面板的日志清理
用宝塔面板的话,面板自带"日志清理"和"日志切割"功能:
- 网站 → 日志:可以查看和清空访问日志
- 也支持在计划任务里定时执行日志切割
如果你完全依赖面板,可以不用手动配 logrotate;但理解 logrotate 的原理有助于排查"为什么日志还是那么大"。
八、常见问题
Q1:加了规则但不自动切?
logrotate 由系统 cron 定时调用(一般每天执行)。检查:
- 规则文件权限和语法正确(先 logrotate -d 测试)
- 是否设置了 daily/weekly 周期
- 日志路径写对没有
Q2:切割后新日志还在写老文件?
postrotate 的 kill -USR1 没生效。确认 pid 路径正确,或日志目录不在 Nginx 默认 path 管理范围(这是宝塔/自定义编译 Nginx 常见坑)。
Q3:直接 rm 删了正在写的日志,导致磁盘没释放?
因为 Nginx 还握着文件句柄,rm 不释放空间。正确做法是用 > 文件 清空而非删除,或执行 kill -USR1 让 Nginx 重建日志文件。
Q4:想保留更久的历史日志?
把 rotate 30 改大,如 rotate 90(保留 90 天),同时确保磁盘够用。
总结
日志切割是服务器日常维护的必做项:用 logrotate 按天轮转、压缩旧日志、设置保留份数,再配合关键的 kill -USR1 让 Nginx 换新日志文件,就能彻底告别"日志撑爆磁盘"。把它和本站的定时任务、磁盘清理教程配合,服务器日志管理这块就圆满了。
