Nginx为什么不要直接用systemctl reload而是用nginx -s reload
subtitle
systemctl reload nginx 和 nginx 的差别
前言
经常有人跟我说不要用 systemctl reload nginx
去重载nginx的配置,要用nginx -s reload
问他为什么他又说不出
(这就好像经常有人跟我说重启节点不要直接用reboot
要用init 6
)
不巧,今天在摸鱼的时候知道大概原因了
我又干了什么
今天在给一个nginx站点更新站点配置的时候对一个站点的conf文件进行了端口分离(原本这个文件里面有两段server配置,80和443)
然后我
cp default_80.conf default_443.conf
接着分别vim了两个配置文件删除了相应的不应该存在的server段
接着顺其自然地
systemctl reload nginx
shell 控制台没报错
继续对配置文件修修改改,猛然看到配置文件里面有这样一段指令
log_format cms_upstream '$remote_addr - $host [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
直觉这里必有妖,因为按照nginx性格,log_format 是不允许被重复定义的,否则会报致命错误
这里立刻去检查nginx error.log
[root@zsxs sites-enabled]# cat /var/log/nginx/error.log 2020/07/11 01:18:51 [emerg] 7467#0: duplicate "log_format" name "cms_upstream" in /etc/nginx/sites-enabled/default_443.conf:3
果然有emergency 错误,也就是换句话说,我的nginx配置是没有重载成功的,嗯?systemctl骗我??
谜底揭晓
众所周知,systemctl reload *** 是执行了对应***的service文件里面的指令
这里把有妖的nginx节点service文件cat出来看看,注意这里是Centos 7.7 + nginx 1.16.1
[root@zsxs nginx]# cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core) [root@zsxs nginx]# nginx -v nginx version: nginx/1.16.1 [root@zsxs sites-enabled]# systemctl status nginx | grep Loaded Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) [root@zsxs sites-enabled]# cat /usr/lib/systemd/system/nginx.service [Unit] Description=The nginx HTTP and reverse proxy server After=network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/run/nginx.pid # Nginx will fail to start if /run/nginx.pid already exists but has the wrong # SELinux context. This might happen when running `nginx -t` from the cmdline. # https://bugzilla.redhat.com/show_bug.cgi?id=1268621 ExecStartPre=/usr/bin/rm -f /run/nginx.pid ExecStartPre=/usr/sbin/nginx -t ExecStart=/usr/sbin/nginx ExecReload=/bin/kill -s HUP $MAINPID KillSignal=SIGQUIT TimeoutStopSec=5 KillMode=process PrivateTmp=true [Install] WantedBy=multi-user.target
可以看到systemctl reload nginx
是执行了/bin/kill -s HUP $MAINPID
命令
也就是向某个PID进程发送了SIGHUP信号
ps: 虽然SIGHUP信号很多文章都会说是终止进程信号,但是更为接近的说法应该是
(转)系统对SIGHUP信号的默认处理是终止收到该信号的进程。所以若程序中没有捕捉该信号,当收到该信号时,进程就会退出。
而根据其他博主文章记载,nginx里面定义了当进程收到SIGHUP信号以后,其并不会退出,而是执行 ngx_reconfigure 操作,也就是配置文件重载
而对于nginx配置是否成功重载,kill -s HUP的返回值都是0 (命令执行成功)
回到文章中,按道理 systemctl reload nginx 是能够报错的(我之前一直这样重载配置文件的..),不过我之前一直用的是ubuntu os,这里来看看ubuntu 16.04(nginx 1.16.1)是怎么写的
root@frpServer:~# cat /etc/issue Ubuntu 16.04.1 LTS \n \l root@frpServer:~# nginx -v nginx version: nginx/1.16.1 root@frpServer:~# cat /lib/systemd/system/nginx.service # Stop dance for nginx # ======================= # # ExecStop sends SIGSTOP (graceful stop) to the nginx process. # If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control # and sends SIGTERM (fast shutdown) to the main process. # After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends # SIGKILL to all the remaining processes in the process group (KillMode=mixed). # # nginx signals reference doc: # http://nginx.org/en/docs/control.html # [Unit] Description=A high performance web server and a reverse proxy server Documentation=man:nginx(8) After=network.target [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid TimeoutStopSec=5 KillMode=mixed [Install] WantedBy=multi-user.target
划重点ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
答案就在这了,ubuntu默认的nginx service文件和centos 里面的nginx service文件reload触发的命令是不一样的
ubuntu 16.04默认的nginx service中reload触发的操作是nginx -g 'daemon on; master_process on;' -s reload
也就是指定了daemon on; master_process on;指令的情况下去发送reload(SIGHUP)信号到nginx master进程
不同于用kill直接发送信号,nginx -s reload命令在nginx重载配置失败的时候,他的返回值是非0的
所以在某些节点上面使用systemctl reload nginx能够重载配置并且知道是否重载成功
本文到这也就差不多了,至于为什么centos和ubuntu里面的service文件有差异,有缘再说吧
然后按照个人习惯决定是否修改centos nginx service里面的ExecReload参数值吧