nginx可以通过信号进行控制。主进程的进程ID默认写在/usr/local/nginx/logs/nginx.pid
。这个名字可能会在配置时期更改,或者可以在nginx.conf
文件中使用pid
指令进行更改。主进程支持下面这些信号:
TERM,INT | fast shutdown |
QUIT | graceful shutdown |
HUP | 更改配置 |
USR1 | 重新打开日志文件 |
USR2 | 更新可执行文件 |
WINCH | 工作进程正常关闭 |
尽管不是强制的,但是单个的工作进程也可以通过信号量进行控制,支持的信号量如下:
TERM, INT | fast shutdown |
QUIT | 正常关机 |
USR1 | 重新打开日志文件 |
WINCH | 异常终止调试(需要debug_points开启) |
更改配置
为了让nginx可以再次读取配置文件,HUP信令应该发送到主进程。主进程会首先进行语法检查,然后尝试应用这些新配置,换句话说,会打开日志文件以及新的监听socket。如果失败的话,它会撤销这些更改,并继续使用旧的配置文件。如果成功的话,它会开启新的工作进程,并请求旧的工作进程正常关闭。旧的工作进程会关闭监听socket,并继续会老客户服务。在所有老客户服务完毕以后,旧的工作进程就会关闭。
举个例子,假设nginx运行在FreeBSD 4.X上,执行:
ps asx -o pid, ppid, user, %cpu, vsz, wchan, command |egrep '(nginx|PID)'
会有下面这些输出:
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)
如果向主进程发送了HUP命令,输出变为了:
PID PPID USER %CPU VSZ WCHAN COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33129 33126 nobody 0.0 1380 kqread nginx: worker process is shutting down (nginx)
33134 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33135 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
PID为33129旧的工作进程之一仍在工作,一段时间后退出:
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 1368 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
日志文件轮转
为了轮转日志文件,需要先为它们命名。将USR1信令发送给主进程后,主进程会重新打开当前的日志文件并将它们分派给一个特权用户,工作进程在这个用户下作为所有者运行。成功开启后,主进程会关闭所有开启的文件并且发送信息给工作进程请求它们重新打开文件。工作进程也会立即开启新的文件并关闭旧的文件。最后,旧文件会立即可用于后置处理,例如压缩。
升级可执行程序
为了升级服务器,首先应该用新的可执行文件替换旧的文件。在USR2信号发送给主进程之后。主进程首先会将与进程ID相关的文件重命名为一个新的以.oldbin
为后缀的文件。例如,/usr/local/nginx/logs/nginx.pid.oldbin
,然后开启一个新的可执行文件,这个可执行文件会反过来开启新的工作进程。
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信号量发送给了第一个主进程,主进程就会发送信息给它的工作进程,请求它们正常关闭,并且它们会开始退出:
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)
-
需要指出的是旧的主进程并不会关闭自己的socket,所以如果需要的话可以重新开启自己的工作进程。如果出于某些原因,新的可执行文件不合适,可以执行下面的操作之一:
- 发送HUP信号量给老的主进程。老的主进程会在不重新读取配置文件的基础上开启新的工作进程,之后,所有的新进程会正常关闭,通过发送QUIT信号量给新的主进程。
-
发送TERM信号量给新的主进程。之后它会发送信息给它的工作进程请求它们立即退出,之后它们会几乎立即退出。(如果出于某些原因新的工作进程没有退出,应该发送
KILL
命令强制它们退出。)当新的主进程退出后,旧的主进程会自动开启新的工作进程。
如果新的主进程退出后旧的主进程就会将进程ID文件名中的.oldbin后缀给去掉。
如果更新成功,旧的主进程会收到QUIT信号,只有新的进程会保留:
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)