概述
本文主要介绍如何在 nginx 运行中,不停止服务的情况下升级 nginx 的版本
前置准备
系统环境:centos7.9
已安装软件:nginx-1.18.0(yum安装)
nginx信号控制
nginx 能够通过信号来进行控制,使用 kill -信号 master进程pid 。master进程pid 可以使用命令 ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)' 获取,或者查看 nginx.pid 文件内容获取。
| 信号 | 说明 |
|---|---|
| TERM, INT | 强制退出 master 进程和 work 进程,直接丢弃未完成的请求 |
| QUIT | 平滑退出 master 进程和 work 进程,处理完已接收的请求,不接收新请求 |
| HUP | 重新读取配置文件,开启新 work 进程,平滑的关闭旧 work 进程 |
| USR1 | 开启新的日志文件 |
| USR2 | 升级 nginx 可执行文件 |
| WINCH | 平滑的退出 work 进程,配合 USR2 实现平滑升级 |
work 进程也可以使用信号控制,本文不做介绍,自行查看官方文档
平滑升级步骤
平滑升级
- 首先把旧的 nginx(yum安装的是
/usr/sbin/nginx)执行文件进行备份,改名为nginx-1.18.0.bak。 - 将新版本的 nginx 解压编译,并将其中
objs/nginx代替旧的 nginx 文件。 - 向旧的 master 进程发送
USR2信号,nginx 将会创建新的 master 进程和新的 worker 进程。 - 向旧的 master 进程发送
WINCH信号,停止旧的 worker 进程。 - 如果升级成功,向旧的 master 进程发送
QUIT信号,停止旧的 master 进程;如果升级失败,请参照下面步骤执行回滚操作。
回滚
- 向旧的 master 进程发送
HUP信号,重新开启旧的 worker 进程。 - 向新的 master 进程发送
QUIT信号, 停止新的 master 进程。
开始升级
本文是将 yum 安装的 nginx-1.18.0 升级为 nginx-1.22.0
下载源码包
下载地址:https://nginx.org/en/download.html
编译可执行文件
创建 /usr/local/server 文件夹,然后上传下载的源码包到此目录。
[root@localhost ~]# mkdir -p /usr/local/server
查看旧 nginx 的配置参数

编译
[root@localhost ~]# cd /usr/local/server
[root@localhost server]# tar zxvf nginx-1.22.0.tar.gz
[root@localhost server]# cd nginx-1.22.0
# 使用与旧 nginx 相同的配置
[root@localhost nginx-1.22.0]# ./configure --prefix=/etc/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 --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --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-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
# 编译,千万不要执行 make install, 否则配置文件等都会被覆盖
[root@localhost nginx-1.22.0]# make
如果编译中出现 C compiler cc is not found 错误信息,需要安装c++, 运行 yum install gcc
如果编译中出现 PCRE 错误信息,运行 yum install pcre-devel
如果编译中出现 openssl 错误信息,运行 yum install openssl openssl-devel
替换可执行文件
# 先备份旧的
[root@localhost nginx-1.22.0]# mv /usr/sbin/nginx /usr/sbin/nginx-1.18.0.bak
# 替换
[root@localhost nginx-1.22.0]# cp objs/nginx /usr/sbin/nginx
开始平滑升级
查看旧 master 进程的 pid,可以看到是 9927
[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
9927 1 root 0.0 46464 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
9928 9927 nginx 0.0 46856 ep_pol nginx: worker process
16746 9799 root 0.0 112812 - grep -E --color=auto (nginx|PID)
发送 USR2 信号, 生成了新的 master 进程,pid 是 16747, 且父进程是旧 master 进程。
[root@localhost nginx-1.22.0]# kill -USR2 9927
[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
9927 1 root 0.0 46464 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
9928 9927 nginx 0.0 46856 ep_pol nginx: worker process
16747 9927 root 0.0 46516 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16748 16747 nginx 0.0 46916 ep_pol nginx: worker process
16750 9799 root 0.0 112816 pipe_w grep -E --color=auto (nginx|PID)
发送 WINCH 信号, 可以看到旧 master 进程 的 work 进程 9928 已经关闭了
[root@localhost nginx-1.22.0]# kill -WINCH 9927
[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
9927 1 root 0.0 46464 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16747 9927 root 0.0 46516 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16748 16747 nginx 0.0 46916 ep_pol nginx: worker process
16777 16759 root 0.0 112812 - grep -E --color=auto (nginx|PID)
验证升级是否成功
通过 curl 访问 nginx 的 index.html 页面(或者浏览器的控制台查看),可以看到 Server 显示为 nginx/1.22.0,表示升级成功
[root@localhost nginx-1.22.0]# curl -i 127.0.0.1
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Wed, 09 Mar 2022 11:16:43 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 29 Oct 2020 15:25:17 GMT
Connection: keep-alive
ETag: "5f9adedd-264"
Accept-Ranges: bytes
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
成功后关闭旧的 master 进程
[root@localhost nginx-1.22.0]# kill -QUIT 9927
[root@localhost nginx-1.22.0]# ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
PID PPID USER %CPU VSZ WCHAN COMMAND
16747 1 root 0.0 46516 sigsus nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
16748 16747 nginx 0.0 46916 ep_pol nginx: worker process
16833 16759 root 0.0 112812 - grep -E --color=auto (nginx|PID)
参考链接
官方文档:https://nginx.org/en/docs/control.html#upgrade
nginx平滑升级:https://www.361shipin.com/blog/1534406139729412096#nginx_68