worker_shutdown_timeout 必须置于 main 块,值需匹配最长连接生命周期,并协同 proxy/client 超时设置;错误位置将被静默忽略,单独配置无效,须闭环上下游超时参数。

排查 Nginx 重载期间旧 worker 进程卡在 shutting down 状态、迟迟不退出,本质是识别并阻断“伪僵尸”——它不是真正的 Z 状态进程,而是处于优雅关闭中却因超时机制缺失或上下游不匹配被无限悬挂的 worker。关键不在杀进程,而在让退出逻辑自然走完或强制兜底。
看状态:区分真僵尸和假“shutdown”
执行 ps aux | grep nginx,重点关注 STAT 列和 CMD 列:
- R / S 状态 + “worker process” + “shutting down”:这是正常中间态,说明旧 worker 正在处理遗留连接,尚未完成退出 —— 不是故障,是等待过程
- Z 状态(STAT=Z):才是真正的僵尸进程,但 Nginx worker 几乎不会变成 Z 态;若出现,大概率是父进程(master)异常崩溃未回收子进程,需检查 master 是否存活、系统是否 OOM
-
D 状态:不可中断睡眠,常见于磁盘 I/O 卡顿(如日志写满、文件系统 hang),此时 kill -9 会损坏数据,必须先查
iostat -x 1和df -h
查日志:定位挂起根源
直接翻 /var/log/nginx/error.log,搜索关键词:
-
open socket .* left in connection:明确表明旧 worker 强制退出前没清理完连接,常因手动 kill -9 或超时设置不合理 -
aborting:紧跟在 shutdown 日志后批量出现,基本可断定是人为干预导致 -
recv() failed.*(104: Connection reset by peer)或upstream timed out:说明下游(后端服务)提前断开,但 Nginx 旧 worker 还在等响应,暴露了proxy_read_timeout小于worker_shutdown_timeout
验配置:确认超时闭环是否生效
该问题几乎总是配置链断裂所致,必须逐项核对:
-
worker_shutdown_timeout 必须在 main 块顶层定义(如
/etc/nginx/nginx.conf最开头),不能在 http/server/events 内;缺配或放错位置 = 完全不生效 -
proxy_read_timeout和proxy_send_timeout≥worker_shutdown_timeout,否则 Nginx 自己先关连接,旧 worker 被悬停 -
client_header_timeout和client_body_timeout≤worker_shutdown_timeout,防止慢客户端拖住旧 worker - WebSocket 场景必须启用:
proxy_http_version 1.1;、proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection "upgrade";
做验证:用可控长请求测试 reload 行为
在某 server 块里加一个测试 location:
location /test-shutdown {
add_header Content-Type text/plain;
return 200 "done after 45s\n";
}然后执行:
-
nginx -t && nginx -s reload(触发重载) - 立刻在另一终端执行:
curl -v http://your-domain/test-shutdown - 观察是否完整返回
done after 45s;若中途断连或返回 502/504,说明 timeout 配置未对齐,旧 worker 被提前切断


















