Nginx日志撑爆磁盘会引发写入失败、缓存中断、进程僵死等连锁故障,需通过du、lsof、iostat定位真实瓶颈,用reload或USR1信号释放空间,并配置logrotate、限制日志大小、调整日志级别及异步写入增强韧性。

日志文件瞬间撑爆磁盘,不是单纯“空间满了”的问题,而是会直接触发 Nginx 写日志失败、临时文件无法落盘、缓存写入中断等一系列连锁反应,严重时表现为进程僵死、请求无响应、甚至 master/worker 进程反复崩溃——这常被误判为“死锁”,实则是资源耗尽型阻塞。
定位真实瓶颈:别只看 df -h
磁盘 100% 只是表象。需同步排查:
-
确认是否真因日志暴涨:执行
du -sh /usr/local/nginx/logs/* 2>/dev/null | sort -hr | head -5,看 access.log/error.log 是否单个超数 GB; -
检查是否有未释放的已删日志:运行
lsof +L1 | grep nginx(比grep deleted更精准),若输出含access.log (deleted),说明句柄仍被占用; -
观察 I/O 等待是否飙升:
iostat -x 1 3中查看%util是否持续 100%,await是否异常高(>100ms),这表明磁盘已处于写入阻塞状态。
立即释放空间:清日志 ≠ 释放磁盘
直接 rm -f access.log 后空间不释放,是因为 Nginx 还握着文件句柄。必须让其重新打开日志文件:
-
首选安全方式:重载配置:
nginx -s reload—— 此操作会优雅关闭旧 worker 日志句柄,新建日志文件,空间立即释放; -
若 reload 失败或无响应:先用
kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)发送 USR1 信号(Nginx 专用日志 reopen 信号); -
极端情况(进程僵死):确认无业务高峰后,
pkill -f "nginx: worker"杀掉 worker 进程(master 会自动拉起),避免kill -9强杀导致残留句柄。
堵住源头:防止再次瞬间打爆
靠人工清理永远被动。必须建立自动防护机制:
-
强制启用 logrotate 并配 postrotate:确保配置中包含
create 0644 nginx nginx和postrotate ... kill -USR1 ... endscript,保证轮转后 Nginx 立即切换到新文件; -
限制单个日志大小:在 logrotate 配置中加
size=100M(而非仅依赖 daily),避免大流量时段单日志突破 10GB; -
关闭非必要日志:如无调试需求,注释掉
access_log off;或改用access_log /dev/null;;错误日志级别调至error,避免大量info级刷盘。
增强系统韧性:降低日志对核心服务的影响
即使日志写入失败,也不应导致服务不可用:
-
设置 error_log 异步写入:在 nginx.conf 的 http 块中添加
error_log /var/log/nginx/error.log warn buffer=64k flush=5s;,缓冲写入并定期刷盘; -
禁用 access_log 缓冲风险项:避免使用
buffer或flush在 access_log 上,因其可能在满缓冲时阻塞请求; - 分离日志存储路径:将 logs 目录挂载到独立小容量 SSD 分区,或通过 mount bind 指向 tmpfs(内存盘),避免影响根分区稳定性。


















