Nginx 通过 systemctl 优雅退出需确保 systemd 服务配置中 KillMode=process、ExecStop=/usr/bin/nginx -s quit,并配合 nginx 原生 quit 信号机制,避免直接 kill。

Nginx 通过 systemctl 管理时,默认已支持优雅退出(graceful shutdown),但需确保服务单元文件配置正确、Nginx 自身支持并启用 graceful 机制,且操作方式得当。核心在于:systemd 的 `ExecStop` 和 `KillMode` 配置要与 Nginx 的 `nginx -s quit` 行为对齐,而非粗暴 `kill`。
确认 Nginx 原生支持优雅退出
Nginx 内置的 quit 信号是优雅退出的关键:
– 它会等待所有工作进程处理完当前请求后才退出;
– 要求主进程未被强制 kill,且工作进程处于可响应状态。
验证方式:
- 手动执行
sudo nginx -s quit(确保配置已重载且无语法错误) - 观察
ps aux | grep nginx:主进程消失,工作进程在几秒内陆续退出,无残留 - 检查日志
/var/log/nginx/error.log,应有类似signal 3 (SIGQUIT) received, exiting
检查并修正 systemd 服务单元配置
默认的 /usr/lib/systemd/system/nginx.service 或 /etc/systemd/system/nginx.service 必须满足以下条件:
- KillMode=process(推荐)或 KillMode=control-group:避免 systemd 对整个 cgroup 发送 SIGKILL
- ExecStop=/usr/bin/nginx -s quit:明确指定优雅退出命令,覆盖默认的 kill 行为
- TimeoutStopSec=30(可选但建议):给足时间让长连接或慢请求完成,避免超时后 fallback 到 SIGKILL
示例关键段落:
[Service] KillMode=process ExecStop=/usr/bin/nginx -s quit TimeoutStopSec=30
使用 systemctl 正确触发优雅退出
执行以下命令才会真正走优雅路径:
-
sudo systemctl stop nginx→ 触发ExecStop,即nginx -s quit -
sudo systemctl reload nginx→ 发送USR2+WINCH,实现平滑升级,也属优雅行为
⚠️ 注意:
– systemctl kill nginx 或 killall nginx 会绕过 ExecStop,直接发送 SIGTERM/SIGKILL,不优雅;
– 若 stop 卡住,先检查 journalctl -u nginx -n 50 是否有阻塞日志(如 keepalive 连接未关闭、proxy_timeout 过长等)。
验证优雅退出是否生效
可通过以下方式交叉确认:
- 执行
sudo systemctl stop nginx后立即运行:sudo ss -tnp | grep :80,观察监听 socket 是否仍在(主进程退出后应消失),同时ps aux | grep 'nginx: worker'应在数秒内清空 - 用
curl -v http://localhost/在 stop 前发起一个长轮询请求(如加sleep 10的后端),看该请求是否能完整返回再退出 - 对比
systemctl stop与kill -TERM $(cat /var/run/nginx.pid)的行为差异:后者若未配 pidfile 或权限不对,可能失败或不优雅










