平滑升级Nginx核心是利用USR2/WINCH/QUIT信号机制实现新旧master共存与无缝切换;新master继承监听端口,旧worker处理完长连接后优雅退出,全程不中断服务、不丢请求、不触发负载均衡摘除。

平滑升级 Nginx 主程序二进制文件,核心是利用 Nginx 的信号机制让新旧 master 进程共存,不中断监听端口、不丢连接、不触发负载均衡器摘除。整个过程无需 stop 或 restart,全部通过向主进程发送信号完成。
确认前提条件
确保以下几项已就绪,否则平滑升级会失败或中途退出:
- 当前 Nginx 是源码编译安装(如
/usr/local/nginx),且你有 root 权限 - 已备份旧二进制:
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak.$(date +%Y%m%d) - 已备份配置目录:
cp -r /usr/local/nginx/conf /usr/local/nginx/conf.bak.$(date +%Y%m%d) - 已下载并解压目标版本源码,用与旧版一致的
./configure参数执行make(不要make install) - 新二进制位于
objs/nginx,且通过nginx -t验证过配置兼容性(尤其注意模块缺失导致的指令报错,如vhost_traffic_status)
替换二进制并启动新 master
这一步让新旧 master 同时运行,共享监听 socket:
- 覆盖旧二进制:
cp -f objs/nginx /usr/local/nginx/sbin/nginx - 查出当前 master 进程 PID:
cat /usr/local/nginx/logs/nginx.pid - 发送 USR2 信号:
kill -USR2 $(cat /usr/local/nginx/logs/nginx.pid) - 此时会生成新 pid 文件
nginx.pid(新 master 的 PID),旧文件自动重命名为nginx.pid.oldbin - 用
ps aux | grep nginx可看到两个 master 进程,以及新旧两组 worker
逐步关停旧 worker 并清理旧 master
旧 worker 继续处理完已有连接,新 worker 接管所有新建请求:
- 向旧 master(即
nginx.pid.oldbin中的 PID)发送 WINCH 信号:kill -WINCH $(cat /usr/local/nginx/logs/nginx.pid.oldbin) - 等待旧 worker 进程数降为 0(
ps aux | grep 'nginx: worker process' | grep -v grep) - 确认新版本运行正常(访问服务、检查日志、验证
nginx -V输出版本号) - 安全关闭旧 master:
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid.oldbin) - 清理残留:
rm -f /usr/local/nginx/logs/nginx.pid.oldbin
异常处理与快速回滚
如果新版本上线后出现 502、连接拒绝或 CPU 异常飙升,可立即切回旧版:
- 向旧 master(若尚未被 QUIT)发 HUP:
kill -HUP $(cat /usr/local/nginx/logs/nginx.pid.oldbin),它会重新拉起旧 worker - 向新 master 发 QUIT:
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid) - 再用旧二进制覆盖回来:
cp /usr/local/nginx/sbin/nginx.bak.* /usr/local/nginx/sbin/nginx - 最后 reload 配置即可恢复原状











