nginx平滑升级
当ngin不是以绝对路径启动的时候 执行make upgrade会报错找不到nginx导致更新失败解决办法
这个问题的核心原因是:make upgrade 依赖 Nginx 的「真实安装路径」与「运行时进程路径」一致,而软链接(ln -s)导致了「启动路径」和「真实路径」不统一,make upgrade 找不到匹配的运行进程,从而失败。
先搞懂:make upgrade 是怎么工作的?
Nginx 的 make upgrade 是「热更新二进制文件」的核心命令,它的工作逻辑是固定的,必须满足两个条件:
- 它会从你当前执行
make upgrade的「Nginx 源码目录」中,读取编译时指定的 真实安装路径(比如--prefix=/usr/local/nginx,则真实二进制文件路径是/usr/local/nginx/sbin/nginx); - 它会检查系统中运行的 Nginx 进程,对应的「二进制文件路径」是否和上面的「真实安装路径」完全一致;
- 只有路径一致,才会替换旧的二进制文件,再给运行中的进程发
USR2信号,实现热更新(不中断服务)。
而你的问题就出在:
- 用软链接启动时(比如
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx),运行nginx实际执行的是软链接,但系统中 Nginx 进程的「路径记录」是 软链接路径(/usr/bin/nginx); - 但
make upgrade找的是 真实安装路径(/usr/local/nginx/sbin/nginx),两者不一致,它就会判定「系统中没有运行中的 Nginx 进程」,直接提示“找不到 Nginx”。
用绝对路径启动时(/usr/local/nginx/sbin/nginx),进程路径和 make upgrade 找的真实路径完全匹配,所以能成功。
解决方案:3种方式,按需选择(从简单到彻底)
核心思路:让 make upgrade 能找到「运行中的 Nginx 进程」,本质是让「进程路径」和「真实安装路径」对齐。
方案一:临时解决(热更新时指定 Nginx 真实路径)
不用改现有软链接(日常仍可 nginx 启动),只在执行 make upgrade 时,显式告诉它 Nginx 的真实二进制文件路径,强制路径匹配:
# 进入 Nginx 源码目录(你当初编译 Nginx 的目录,比如 /root/nginx-1.24.0)
cd /root/nginx-1.24.0
# 执行 make upgrade 时,用 NGINX_PATH 指定真实路径(替换成你的真实路径)
make upgrade NGINX_PATH=/usr/local/nginx/sbin/nginx
✅ 原理:NGINX_PATH 参数会覆盖 make upgrade 默认的路径查找逻辑,直接指向真实安装的 Nginx 二进制文件,无论你用软链接还是绝对路径启动,只要进程是这个真实文件运行的,就能匹配成功。
方案二:彻底解决(让软链接启动的进程路径=真实路径)
如果想日常用 nginx 启动,且 make upgrade 无需额外参数,核心是让「软链接启动时,进程记录的是真实路径」。问题出在你的软链接可能是「相对路径软链接」或「路径层级不匹配」,需要重新创建「绝对路径软链接」并确保路径对齐:
-
先确认 Nginx 的真实路径(关键!必须先找到真实安装的二进制文件):
# 方法1:查看软链接指向的真实路径 readlink -f $(which nginx) # 示例输出(真实路径):/usr/local/nginx/sbin/nginx # 方法2:如果没软链接,直接找编译时的路径(比如默认 --prefix=/usr/local/nginx) find / -name nginx -type f -executable 2>/dev/null -
删除旧的软链接(如果路径不对):
# 假设旧软链接是 /usr/bin/nginx,先删除 rm -f /usr/bin/nginx -
创建「指向真实路径的绝对路径软链接」:
# 语法:ln -s 真实二进制文件路径 软链接路径 ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx -
用软链接启动 Nginx 后,验证进程路径:
# 停止旧的 Nginx 进程(确保完全停止) nginx -s stop # 用软链接启动 nginx # 查看运行中的 Nginx 进程路径(重点看 CMD 列) ps aux | grep nginx | grep -v grep✅ 正确结果:CMD 列显示的是 真实路径(
/usr/local/nginx/sbin/nginx),而非软链接路径(/usr/bin/nginx)。
(如果仍显示软链接路径,说明系统有hash缓存,执行hash -d nginx清除缓存后,重新启动即可) -
此时执行
make upgrade(在 Nginx 源码目录),无需额外参数,就能成功:cd /root/nginx-1.24.0 make upgrade
方案三:终极方案(不用软链接,用环境变量统一路径)
如果不想依赖软链接,避免路径混乱,直接把 Nginx 的 sbin 目录加入系统环境变量,既不用输绝对路径,也能让 make upgrade 路径一致:
-
添加环境变量(永久生效):
# 编辑环境变量配置文件(全局生效,所有用户可用) vi /etc/profile # 或只对当前用户生效:vi ~/.bashrc在文件末尾添加一行(替换成你的 Nginx
sbin真实路径):export PATH=$PATH:/usr/local/nginx/sbin -
生效环境变量:
# 全局配置生效:source /etc/profile # 当前用户配置生效:source ~/.bashrc -
验证环境变量:
# 执行后显示 Nginx 真实路径,说明生效 which nginx # 示例输出:/usr/local/nginx/sbin/nginx -
后续操作:
- 启动 Nginx:直接输
nginx(本质是执行环境变量中的真实路径); - 热更新:
cd 源码目录 && make upgrade(路径完全一致,不会报错)。
- 启动 Nginx:直接输
关键原因总结(避免再踩坑)
make upgrade不关心你“怎么启动”,只关心「运行中的 Nginx 进程对应的二进制文件路径」和「编译时的真实安装路径」是否一致;- 软链接启动失败,是因为进程路径记录的是软链接路径(而非真实路径),导致
make upgrade匹配失败; - 绝对路径启动成功,是因为进程路径和真实安装路径完全一致。
额外提醒(热更新注意事项)
- 执行
make upgrade前,必须在「当前要升级的 Nginx 源码目录」中执行(比如你下载的 Nginx 1.24.0 源码目录),不能在其他目录; - 热更新前建议备份旧的二进制文件:
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak,避免升级失败无法回滚; - 升级后验证:
nginx -v查看版本是否更新,ps aux | grep nginx查看进程是否正常运行(不会中断现有连接)。
按上面的方案操作后,无论是日常启动(输入 nginx),还是热更新(make upgrade),都能正常工作,不用再依赖绝对路径~
官网下载最新的安装版
下载地址
https://nginx.org/en/download.html

将下载的包上传到服务器后进行更新操作
解压
tar xf nginx-1.27.0.tar.gz -C /usr/src
查看当前nginx配置参数
nginx -v
nginx version: nginx/1.24.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-stream --with-stream_realip_module --with-stream_ssl_module
在新版本中进行编译
cd /usr/src/nginx-1.27.0/ && ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-stream --with-stream_realip_module --with-stream_ssl_module
make
无需make install
对原来的nginx进行备份
where nginx
cd /usr/local/nginx/sbin
mv nginx nginx-1.24.0old
cd /usr/src/nginx-1.27.0/objs
cp ./nginx /usr/local/nginx/sbin/
nginx -V
nginx version: nginx/1.27.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-stream --with-stream_realip_module --with-stream_ssl_module
进行平滑升级替换
ps aux|grep nginx
可看到当前有一个master进程
发送信号给老版本进程
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
向旧版本的 master 进程发送 WINCH 信号,并逐步关闭自己的工作进程(master 进程不退出),这时所有的用户请求都会由新版本的 master 进程处理。
kill -WINCH oldpid
然后平滑关闭老进程
kill -QUIT `more /usr/local/nginx/logs/nginx.pid.oldbin`


浙公网安备 33010602011771号