我們在開發中常需要啟動長時間運行的程式,需要在關閉ssh連接時,仍然保持程式正常運行,為此我們需要用到nohup命令。當然也可以使用screen命令,我在之前的文章中已有介紹,可以參考。 nohup命令使用起來並不難,之前我也並沒有深入的瞭解。在最近的開發過程中由於需要啟動代理服務,因此使用了noh ...
我們在開發中常需要啟動長時間運行的程式,需要在關閉ssh連接時,仍然保持程式正常運行,為此我們需要用到nohup命令。當然也可以使用screen命令,我在之前的文章中已有介紹,可以參考。
nohup命令使用起來並不難,之前我也並沒有深入的瞭解。在最近的開發過程中由於需要啟動代理服務,因此使用了nohup命令。但卻發現代理服務在關閉ssh連接一段時間之後就會掛掉,因此簡單瞭解了一下nohup,在此記錄下。在解決這個問題的過程中,我也嘗試使用screen命令,但也沒有解決,問題比較奇怪,看現象應該是與代理服務本身以及伺服器配置有關。
nohup命令是用來執行其他命令的,同時忽略SIGHUP信號。當我們關閉ssh連接時,操作系統會向正在運行的程式發送SIGHUP信號,通常情況下這個信號會使進程退出,但nohup命令會忽略這個信號。
我們先瞭解下Linux中的幾個概念:
-
進程組:一個或多個進程的集合,每一個進程組有唯一的一個進程組ID,即進程組長進程的ID。
-
會話期:一個或多個進程組的集合,有唯一的一個會話期首進程(session leader)。會話期ID為首進程的ID。
-
會話期可以有一個單獨的控制終端(controlling terminal)。與控制終端連接的會話期首進程叫做控制進程(controlling process)。當前與終端交互的進程稱為前臺進程組,其餘進程組稱為後臺進程組。
根據POSIX.1定義:
-
掛斷信號(SIGHUP)預設的動作是終止程式。
-
當終端介面檢測到網路連接斷開,將掛斷信號發送給控制進程(會話期首進程)。
-
如果會話期首進程終止,則該信號發送到該會話期前臺進程組。
-
一個進程退出導致一個孤兒進程組產生時,如果任意一個孤兒進程組進程處於STOP狀態,發送SIGHUP和SIGCONT信號到該進程組中所有進程。
因此當網路斷開或終端視窗關閉後,也就是ssh連接斷開以後,控制進程收到SIGHUP信號退出,會導致該會話期內其他進程退出。
使用後臺運行命令“&”並沒有擺脫ssh進程組控制,只是把進程放入了後臺進程組。在關閉ssh連接時,同樣會退出程式。
之前我們介紹了screen命令,這裡把nohup命令和screen命令做一下對比:
-
nohup命令只保證單個指定進程不退出,screen命令會保留整個會話期內的所有進程;
-
nohup命令相對簡單,對於複雜的人機交互還是需要screen命令;
-
nohup命令執行的程式只能通過kill命令來殺死,而screen命令可以更友好些;
-
screen命令可以保留會話的環境設置,通過恢復會話,可以實現工作環境的快速切換;
-
相對而言nohup占用資源更少,沒有交互需求的時候,nohup就能滿足需要了;
screen是可以完全替代nohup的。從個人偏好來說,也更喜歡screen,方便且強大:)