nginx平滑升级

当ngin不是以绝对路径启动的时候 执行make upgrade会报错找不到nginx导致更新失败解决办法

这个问题的核心原因是:make upgrade 依赖 Nginx 的「真实安装路径」与「运行时进程路径」一致,而软链接(ln -s)导致了「启动路径」和「真实路径」不统一,make upgrade 找不到匹配的运行进程,从而失败。

先搞懂:make upgrade 是怎么工作的?

Nginx 的 make upgrade 是「热更新二进制文件」的核心命令,它的工作逻辑是固定的,必须满足两个条件:

  1. 它会从你当前执行 make upgrade 的「Nginx 源码目录」中,读取编译时指定的 真实安装路径(比如 --prefix=/usr/local/nginx,则真实二进制文件路径是 /usr/local/nginx/sbin/nginx);
  2. 它会检查系统中运行的 Nginx 进程,对应的「二进制文件路径」是否和上面的「真实安装路径」完全一致;
  3. 只有路径一致,才会替换旧的二进制文件,再给运行中的进程发 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 无需额外参数,核心是让「软链接启动时,进程记录的是真实路径」。问题出在你的软链接可能是「相对路径软链接」或「路径层级不匹配」,需要重新创建「绝对路径软链接」并确保路径对齐:

  1. 先确认 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
    
  2. 删除旧的软链接(如果路径不对)

    # 假设旧软链接是 /usr/bin/nginx,先删除
    rm -f /usr/bin/nginx
    
  3. 创建「指向真实路径的绝对路径软链接」

    # 语法:ln -s 真实二进制文件路径 软链接路径
    ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
    
  4. 用软链接启动 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 清除缓存后,重新启动即可)

  5. 此时执行 make upgrade(在 Nginx 源码目录),无需额外参数,就能成功:

    cd /root/nginx-1.24.0
    make upgrade
    

方案三:终极方案(不用软链接,用环境变量统一路径)

如果不想依赖软链接,避免路径混乱,直接把 Nginx 的 sbin 目录加入系统环境变量,既不用输绝对路径,也能让 make upgrade 路径一致:

  1. 添加环境变量(永久生效)

    # 编辑环境变量配置文件(全局生效,所有用户可用)
    vi /etc/profile
    # 或只对当前用户生效:vi ~/.bashrc
    

    在文件末尾添加一行(替换成你的 Nginx sbin 真实路径):

    export PATH=$PATH:/usr/local/nginx/sbin
    
  2. 生效环境变量

    # 全局配置生效:source /etc/profile
    # 当前用户配置生效:source ~/.bashrc
    
  3. 验证环境变量

    # 执行后显示 Nginx 真实路径,说明生效
    which nginx
    # 示例输出:/usr/local/nginx/sbin/nginx
    
  4. 后续操作:

    • 启动 Nginx:直接输 nginx(本质是执行环境变量中的真实路径);
    • 热更新:cd 源码目录 && make upgrade(路径完全一致,不会报错)。

关键原因总结(避免再踩坑)

  1. make upgrade 不关心你“怎么启动”,只关心「运行中的 Nginx 进程对应的二进制文件路径」和「编译时的真实安装路径」是否一致;
  2. 软链接启动失败,是因为进程路径记录的是软链接路径(而非真实路径),导致 make upgrade 匹配失败;
  3. 绝对路径启动成功,是因为进程路径和真实安装路径完全一致。

额外提醒(热更新注意事项)

  1. 执行 make upgrade 前,必须在「当前要升级的 Nginx 源码目录」中执行(比如你下载的 Nginx 1.24.0 源码目录),不能在其他目录;
  2. 热更新前建议备份旧的二进制文件:cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak,避免升级失败无法回滚;
  3. 升级后验证:nginx -v 查看版本是否更新,ps aux | grep nginx 查看进程是否正常运行(不会中断现有连接)。

按上面的方案操作后,无论是日常启动(输入 nginx),还是热更新(make upgrade),都能正常工作,不用再依赖绝对路径~


官网下载最新的安装版

下载地址
https://nginx.org/en/download.html
image

将下载的包上传到服务器后进行更新操作

解压

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`

image

posted @ 2024-07-25 11:34  开心burukku  阅读(52)  评论(0)    收藏  举报