nginx -s reload 仅重载配置而不升级版本,因HUP信号不替换二进制文件;版本升级需USR2/WINCH/QUIT组合信号实现新旧进程平滑交接。

零停机热升级不是靠“重启”实现的,而是靠新旧二进制共存 + 信号驱动的进程交接。HUP 信号只管配置更新,换版本必须用 USR2/WINCH/QUIT 这套组合。
为什么 nginx -s reload 不能升级版本
HUP 信号(即 nginx -s reload)只会让 Master 重新解析配置、启动新 Worker,但所有 Worker 仍使用**当前正在运行的二进制文件**。它不加载新编译出的 nginx 可执行文件,所以版本不会变。
- 现象:执行
nginx -s reload后nginx -v输出仍是旧版本 - 本质:HUP 是配置热重载,不是二进制热替换
- 风险:若误以为 reload 就完成了升级,实际漏洞或新特性根本没生效
USR2 信号触发新 Master 启动的关键细节
发送 kill -USR2 不是“启动新 nginx”,而是让**当前 Master 进程 fork 出一个新 Master**,这个新 Master 会主动去加载你放在原路径的新二进制文件。
- 必须确保新二进制已就位且权限一致:比如旧版在
/usr/sbin/nginx,新二进制就得放这里(或通过软链指向它) - PID 文件会被自动重命名:原
/var/run/nginx.pid变成/var/run/nginx.pid.oldbin,新 Master 写入新的nginx.pid - 常见错误:
Text file busy—— 表示旧 Worker 还在用旧二进制,此时不能直接cp覆盖,改用mv原子替换
WINCH 和 QUIT 信号的执行顺序不能颠倒
旧 Master 仍在运行时,kill -WINCH 是通知它关掉自己管理的 Worker;而 kill -QUIT 是终止它自己。顺序错或漏一步,就会残留旧进程。
- 先发
kill -WINCH $(cat /var/run/nginx.pid.oldbin):旧 Worker 进入 graceful shutdown,不再 accept 新连接 - 等
ps aux | grep "nginx: worker process" | grep -v "master"返回空,说明旧 Worker 全退出 - 再发
kill -QUIT $(cat /var/run/nginx.pid.oldbin):干掉旧 Master;注意此时要用.oldbin对应的 PID 文件 - 如果跳过 WINCH 直接 QUIT,旧 Worker 会被强制 kill,正在传输的请求可能中断(如大文件上传失败)
验证是否真升级成功,别只信 nginx -v
nginx -v 显示的是命令行里那个 nginx 二进制的版本,不是当前运行进程的实际版本。真正运行的是哪个,得看进程打开的文件。
- 查真实运行的二进制:
ls -l /proc/$(pgrep -f "nginx: master process")/exe,输出路径应指向你部署的新文件 - 确认新 Worker 已接管:
ps -eo pid,comm,lstart | grep nginx | grep worker,看启动时间是否晚于 USR2 操作时刻 - 检查模块是否加载:若新版本加了
--with-http_v2_module,可用curl -I --http2 https://your.site验证协议是否生效
最容易被忽略的是配置兼容性——新旧版本对同一份配置的解析行为可能不同。比如 1.24+ 默认禁用 SSLv3,而旧配置里写了 ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2,reload 会失败,但 USR2 启动新 Master 时也会卡在这一步,只是日志里容易被淹没。











