nginx热升级需源码安装、复用旧configure参数、禁用make install;通过usr2启新master、winch关旧worker、quit退旧master三步信号实现零中断,全程依赖pid精准控制与严格验证。

热升级 Nginx 二进制主程序本身就能做到不挂业务,但必须绕开“重载配置”(nginx -s reload)这个常见误区——它只重载配置,不替换程序。真正零中断升级二进制,靠的是进程信号协同与新旧 master 并行机制。
确认前提:源码安装 + 原生启动 + 参数一致
这三步跳过,90%会卡在 USR2 阶段失败:
-
必须是源码编译安装:如
/usr/local/nginx/sbin/nginx启动,而非systemctl start nginx;后者会被 systemd 拦截信号,USR2 不生效 -
必须复用旧版 configure 参数:运行
nginx -V(大写 V),完整抄下--prefix、--conf-path、所有--with-xxx-module(比如--with-http_ssl_module),缺一个模块,nginx -t就报错 -
不能用 make install:它会覆盖 conf/、html/ 目录,导致配置丢失或静态页被重置;只执行
make,新二进制只存在于objs/nginx
替换二进制并备份
操作前先备份,防止覆盖失败或文件忙:
- 执行
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak - 编译好新版本后,用
cp -f objs/nginx /usr/local/nginx/sbin/覆盖(-f强制处理 “Text file busy”) - 确保新旧二进制权限一致(如
chmod +x),否则新 master 启动时直接拒绝
按顺序发三个信号,一步都不能错
信号依赖严格,PID 来源和目标必须精准:
-
发 USR2 启动新 master:
kill -USR2 $(cat /usr/local/nginx/logs/nginx.pid)→ 此时ps aux | grep nginx应显示两组进程(旧 master + worker,新 master + worker),新 PID 写入nginx.pid,旧 PID 自动重命名为nginx.pid.oldbin -
发 WINCH 关旧 worker:
kill -WINCH $(cat /usr/local/nginx/logs/nginx.pid.oldbin)→ 仅关闭旧 worker,不碰旧 master;旧 worker 处理完存量请求后自动退出,期间新 worker 已开始接新流量 -
发 QUIT 退旧 master:
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid.oldbin)→ 等旧 worker 全退出后再执行;成功后nginx.pid.oldbin自动删除,只剩新 master + 新 worker
验证与回滚兜底
升级不是发完信号就结束,必须闭环验证:
- 查版本:
nginx -v看是否为新版本;nginx -V确认模块列表无缺失 - 查进程:
ps aux | grep nginx应只剩一组(无 oldbin 进程),且 worker 用户与旧版一致(如www-data或nginx) - 查日志:
tail -f /usr/local/nginx/logs/error.log观察有无模块加载失败或 bind 错误 - 异常回滚:
kill -HUP $(cat /usr/local/nginx/logs/nginx.pid.oldbin)让旧 master 重启 worker,再kill -QUIT新 master 即可秒级切回











