Nginx主进程收到SIGQUIT后执行三步协作关闭:先关闭监听套接字停新连接,再通过IPC向worker发送QUIT指令,最后等待worker自然退出;worker收到后置标志、拒新连、处理完存量请求再退出。

Master 进程收到 SIGQUIT 时,并不直接退出,而是启动一套协作式关闭流程:先停新连接、再清旧流量、最后等 Worker 自行退出。关键不在“杀进程”,而在“协调状态”。
主进程收到 SIGQUIT 后的三步动作
主进程不是一收到信号就关自己,而是按顺序执行:
- 立即关闭所有监听套接字(
ngx_close_listening_sockets()),不再 accept 任何新连接,但已建立的 TCP 连接和正在处理的请求保持活跃 - 通过已建立的 channel socket 向每个 worker 进程发送 QUIT 指令(不是用 kill 发信号,是走内部 IPC 通道)
- 进入等待循环,持续检查 worker 进程是否全部退出;若超时(默认无硬性超时,但可通过
worker_shutdown_timeout配置),可人工干预
Worker 进程如何响应 QUIT 指令
Worker 不依赖系统信号处理器,而是轮询主进程发来的指令:
- 收到 QUIT 后,将内部标志
ngx_exiting = 1,进入“退出中”状态 - 停止调用
accept(),拒绝新连接;但继续处理事件队列中的请求、定时器、已有连接上的读写 - 待所有活跃连接自然关闭(或超时断开)、所有 pending 任务完成,才调用
ngx_worker_process_exit()清理资源并退出
为什么不能靠信号量或简单 kill
常见误区是以为用信号量同步或直接 kill -9 就能关干净,实际会出问题:
- 信号量需显式创建/等待/释放,而 Nginx 关闭流程无共享临界区,不需要互斥保护
- 直接向 worker 发
SIGQUIT或SIGTERM可能被忽略或中断,Nginx 选择自主 IPC 指令更可靠 - 若主进程在 worker 未退出前强行退出,会导致残留 worker 和 pid 文件,甚至出现“多 master”异常
验证与调试建议
排查优雅退出是否生效,可结合日志和系统状态观察:
- 查看 error log 中是否有
"exiting" "shutdown" "exited"等关键词,确认各阶段触发 - 用
ss -tulnp | grep nginx观察监听端口是否消失,确认主进程已关监听 - 用
ps aux | grep nginx查看 worker 进程是否逐个退出,而非瞬间全无 - 若发现旧 master 残留,检查是否所有 worker 已真正退出(
ngx_processes[i].exited == 1)










