陈吟哥哥

Nginx编译安装的升级

Table of Contents

对于正常的网站来说,每时每刻都有流量进入,在切换版本的时候可以使用负载均衡,停止要升级的Nginx,但是因为某些原因可能只有一台Nginx,那么就要在升级的时候尽量减少对线上环境的影响。

# 下载新版本Nginx包

前往Nginx官方网站下载新版本。

Nginx有两个主要的版本发布线路。

  1. MainLine version是开发版本,包含了最新的功能和改进。如果你想尝试新功能的话可以使用这个版本。

  2. Stable version是稳定版本,适合生产环境。如果没有特殊需求,可以使用这个版本。

downloads

这里我将要把我的Nginx更新到最新版,我选择了Nginx 1.26版本。

对于稳定版本,共有五个链接分别指的是。

  1. 版本信息,包含主要变更信息

  2. linux版本安装包

  3. linux版本签名校验文件

  4. Windows版本安装包

  5. Windows版本签名校验文件

我的服务器环境是Debian12,下面以Linux环境root用户进行操作,如果你使用的是具有sudo权限的普通用户,注意在命令前添加sudo。

复制Linux版本安装包URL,在终端中输入。

wget https://nginx.org/download/nginx-1.26.0.tar.gz

# 编译Nginx

解压缩安装包

tar -zvxf nginx-1.26.0.tar.gz

查看旧版本nginx信息

nginx -V

可以看到当前版本的nginx使用的配置参数。

nginx version: nginx/1.25.2
built by gcc 11.3.1 20221121 (Red Hat 11.3.1-4) (GCC)
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' --with-stream

进入新版本的安装包目录,并且进行配置。

cd nginx-1.26.0
./configure  --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' --with-stream

然后进行编译并且安装。如果你之前就是本机编译安装的,那么这次也不会缺少依赖。

make && make install

如果有报错,那么你需要解决编译问题,才可以进行下一步操作。

# 版本更新

我们需要跟踪Nginx进程的运行情况,以便可以更好的观察到执行命令时发生了什么。

ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'

上述命令会显示nginx进程的进程ID,父进程ID,用户,cpu占用率,虚拟内存,进程等待的资源,进程的执行命令等信息。

 PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
33127 33126 nobody   0.0  1380 kqread nginx: worker process (nginx)
33128 33126 nobody   0.0  1364 kqread nginx: worker process (nginx)
33129 33126 nobody   0.0  1364 kqread nginx: worker process (nginx)

下面,需要对主进程发送USR2信号,这样主进程会把进程ID的文件重命名为带有.oldbin后缀的新文件,然后会启动一个新的可执行文件即我们刚刚编译的程序,然后新的主程序会启动新的工作进程。一般来说,pid文件是在编译参数中指定的,例如--pid-path=/run/nginx.pid

kill -USR2 33126

再次运行命令,查看当前的Nginx程序运行情况

 PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
33134 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
33135 33126 nobody   0.0  1380 kqread nginx: worker process (nginx)
33136 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

现在新的和旧的程序都在工作,我们向旧程序发送WINCH信号,让旧主程序结束它的工作进程。

kill -WINCH 33126

随着时间的推移。可以发现旧主程序的工作进程在完成任务后会自动退出。

  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
33135 33126 nobody   0.0  1380 kqread nginx: worker process is shutting down (nginx)
36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

只会剩下新主程序和它的工作进程处理请求

  PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

值得注意的是,旧的主程序不会关闭它监听的套接字。这样的话,如果你的新主程序因为某些原因不能正常工作,那么你可以重新启动旧主程序的工作进程。下面提供两种方法,你可以任选其一。

  1. 向旧主程序发送HUP信号,启动它的工作进程。然后向新主程序发送QUIT信号,关闭新主程序和它的工作进程。

    kill -HUP 33126
    kill -QUIT 36264
    
  2. 向新主程序发送TERM信号,这样新主程序会给它的工作进程发送信息,要求工作进程立即退出,如果新的工作进程因为某些原因没有退出,那么你需要向其发送KILL信号,让其强制退出。

    kill -TERM 36264
    

如果你没有出现上面的情况,那么你就升级成功了,那么你需要向旧主程序发送QUIT信号,要求其退出,它会自动关闭旧主程序和它的工作进程。这样,你就可以只保留新主程序及其工作程序。

kill -QUIT 33126

最后可以观察到我们已经成功更新了Nginx程序。

PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
36264     1 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)