我們常常會碰到這樣的問題,想要在Linux 伺服器執行一些耗時較長的任務, 結果卻因為網路的不穩定性導致任務中途失敗。如何讓指令提交後不受本地關閉終端機視窗/網路斷開連線的干擾呢?
以下列舉了三種方法,可以很方便的滿足上述需求。
問題分析:
我們知道,當使用者登出(logout)或網路斷開時,終端機會收到 HUP(hangup)訊號從而關閉其所有子程序。因此,我們的解決辦法就有兩種途徑:要麼讓進程忽略 HUP 訊號,要麼讓進程運行在新的會話裡從而成為不屬於此終端的子進程。
三種解決方法:
nohup 無疑是我們首先想到的方法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup 訊號。
nohup 的使用是十分方便的,只需在要處理的指令前加上 nohup 即可,標準輸出和標準錯誤缺省會被重定向到 nohup.out 檔案。一般我們可在結尾加上"&"來將指令同時放入後台運行,也可用">filename 2>&1"來更改缺省的重定向檔名。
nohup 範例
[root@pythontab ~]# nohup ping www.php.cn & [1] 3059 nohup: appending output to `nohup.out' [root@pythontab ~]# ps -ef |grep 3059 root 3059 984 0 15:06 pts/3 00:00:00 ping www.php.cn root 3067 984 0 15:06 pts/3 00:00:00 grep 3059 [root@pythontab ~]#
nohup 無疑能透過忽略HUP 訊號來使我們的進程避免中途被中斷,但如果我們換個角度思考,如果我們的進程不屬於接受HUP 訊號的終端的子進程,那麼自然也就不會受到HUP 訊號的影響了。 setsid 就能幫助我們做到這一點。
setsid 的使用也是非常方便的,也只需在要處理的指令前加上 setsid 即可。
setsid 範例
[root@pythontab ~]# setsid ping www.php.cn [root@pythontab ~]# ps -ef |grep www.php.cn root 31094 1 0 07:28 ? 00:00:00 ping www.php.cn root 31102 29217 0 07:29 pts/4 00:00:00 grep www.php.cn [root@pythontab ~]#
值得注意的是,上例中我們的進程ID(PID)為31094,而它的父ID(PPID)為1(即為init進程ID),並不是目前終端的進程ID。
這裡還有一個關於 subshell 的小技巧。我們知道,將一個或多個命名包含在「()」中就能讓這些命令在子 shell 中運行中,從而擴展出許多有趣的功能,我們現在要討論的就是其中之一。
當我們將"&"也放入「()」內之後,我們會發現所提交的作業並不在作業列表中,也就是說,是無法透過jobs來查看的。讓我們來看看為什麼這樣就能躲過 HUP 訊號的影響。
subshell 範例
[root@pythontab ~]# (ping www.php.cn &) [root@pythontab ~]# ps -ef |grep www.php.cn root 16270 1 0 16:13 pts/4 00:00:00 ping www.php.cn root 16278 15362 0 16:13 pts/4 00:00:00 grep www.php.cn [root@pythontab ~]#
從上例可以看出,新提交的進程的父 ID(PPID)為1(init 進程的 PID),並不是目前終端的進程 ID。因此並不屬於目前終端的子進程,因此也就不會受到目前終端的 HUP 訊號的影響了。
比較而言,我比較喜歡用setsid,簡單又實用。當然,這裡看大家喜好即可,效果上差異不大。
以上是Linux下系統後台運作的方法講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!