控制 nginx

變更設定
輪換日誌檔
即時升級可執行檔

nginx 可以透過訊號來控制。預設情況下,主程序的程序 ID 會寫入 /usr/local/nginx/logs/nginx.pid 檔案中。此名稱可以在設定時變更,或者在 nginx.conf 中使用 pid 指令變更。主程序支援以下訊號

TERM, INT快速關閉
QUIT優雅關閉
HUP變更設定,跟上時區變更(僅適用於 FreeBSD 和 Linux),使用新設定啟動新的 worker 程序,優雅關閉舊的 worker 程序
USR1重新開啟日誌檔
USR2升級可執行檔
WINCH優雅關閉 worker 程序

個別的 worker 程序也可以透過訊號控制,儘管不是必須的。支援的訊號如下

TERM, INT快速關閉
QUIT優雅關閉
USR1重新開啟日誌檔
WINCH異常終止以進行偵錯(需要啟用 debug_points

變更設定

為了讓 nginx 重新讀取設定檔,應向主程序傳送 HUP 訊號。主程序首先檢查語法有效性,然後嘗試套用新設定,也就是開啟日誌檔和新的監聽 socket。如果失敗,則會回滾變更並繼續使用舊設定。如果成功,則會啟動新的 worker 程序,並向舊的 worker 程序傳送訊息,要求它們優雅關閉。舊的 worker 程序會關閉監聽 socket 並繼續服務舊的用戶端。在所有用戶端都服務完畢後,舊的 worker 程序會關閉。

讓我們用例子來說明。假設 nginx 在 FreeBSD 上執行,命令

ps axw -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 的舊 worker 程序仍然繼續運作。過一段時間後,它會退出

  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 訊號。主程序將重新開啟所有目前開啟的日誌檔,並將執行 worker 程序時所使用的非特權使用者指定為擁有者。成功重新開啟後,主程序會關閉所有開啟的檔案,並向 worker 程序傳送訊息,要求它們重新開啟檔案。Worker 程序也會立即開啟新檔案並關閉舊檔案。如此一來,舊檔案幾乎可以立即用於後處理,例如壓縮。

即時升級可執行檔

為了升級伺服器可執行檔,應首先將新的可執行檔放在舊檔案的位置。之後,應向主程序傳送 USR2 訊號。主程序首先會將其程序 ID 的檔案重新命名為新的檔案,並加上 .oldbin 後綴,例如 /usr/local/nginx/logs/nginx.pid.oldbin,然後啟動新的可執行檔,而新的可執行檔又會啟動新的 worker 程序

  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)

之後,所有 worker 程序(舊的和新的)都會繼續接受請求。如果向第一個主程序傳送 WINCH 訊號,它會向其 worker 程序傳送訊息,要求它們優雅關閉,它們將開始退出

  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)

過一段時間後,只有新的 worker 程序會處理請求

  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,如果需要,可以管理它再次啟動其 worker 程序。如果因為某些原因,新的可執行檔無法接受地運作,可以執行以下操作之一

如果新的主程序退出,則舊的主程序會從程序 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)