Linux讓程式在後臺執行的三種方法

pythontab發表於2015-10-16

我們經常會碰到這樣的問題,想要在Linux 伺服器執行一些耗時較長的任務, 結果卻由於網路的不穩定導致任務中途失敗。如何讓命令提交後不受本地關閉終端視窗/網路斷開連線的干擾呢?

下面列舉了三種方法,可以很方便的滿足上述需求。


問題分析:

我們知道,當使用者登出(logout)或者網路斷開時,終端會收到 HUP(hangup)訊號從而關閉其所有子程式。因此,我們的解決辦法就有兩種途徑:要麼讓程式忽略 HUP 訊號,要麼讓程式執行在新的會話裡從而成為不屬於此終端的子程式。

三種解決辦法:

1. nohup

nohup 無疑是我們首先想到的辦法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup 訊號。

nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標準輸出和標準錯誤預設會被重定向到 nohup.out 檔案中。一般我們可在結尾加上"&"來將命令同時放入後臺執行,也可用">filename 2>&1"來更改預設的重定向檔名。

nohup 示例

[root@pythontab ~]# nohup ping www.pythontab.com &
[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.pythontab.com
root      3067   984  0 15:06 pts/3    00:00:00 grep 3059
[root@pythontab ~]#

2。setsid

nohup 無疑能透過忽略 HUP 訊號來使我們的程式避免中途被中斷,但如果我們換個角度思考,如果我們的程式不屬於接受 HUP 訊號的終端的子程式,那麼自然也就不會受到 HUP 訊號的影響了。setsid 就能幫助我們做到這一點。

setsid 的使用也是非常方便的,也只需在要處理的命令前加上 setsid 即可。

setsid 示例

[root@pythontab ~]# setsid ping www.pythontab.com
[root@pythontab ~]# ps -ef |grep www.pythontab.com
root     31094     1  0 07:28 ?        00:00:00 ping www.pythontab.com
root     31102 29217  0 07:29 pts/4    00:00:00 grep www.pythontab.com
[root@pythontab ~]#

值得注意的是,上例中我們的程式 ID(PID)為31094,而它的父 ID(PPID)為1(即為 init 程式 ID),並不是當前終端的程式 ID。

3。& subshell

這裡還有一個關於 subshell 的小技巧。我們知道,將一個或多個命名包含在“()”中就能讓這些命令在子 shell 中執行中,從而擴充套件出很多有趣的功能,我們現在要討論的就是其中之一。

當我們將"&"也放入“()”內之後,我們就會發現所提交的作業並不在作業列表中,也就是說,是無法透過jobs來檢視的。讓我們來看看為什麼這樣就能躲過 HUP 訊號的影響吧。

subshell 示例

[root@pythontab ~]# (ping www.pythontab.com &)
[root@pythontab ~]# ps -ef |grep www.pythontab.com
root     16270     1  0 16:13 pts/4    00:00:00 ping www.pythontab.com
root     16278 15362  0 16:13 pts/4    00:00:00 grep www.pythontab.com
[root@pythontab ~]#

從上例中可以看出,新提交的程式的父 ID(PPID)為1(init 程式的 PID),並不是當前終端的程式 ID。因此並不屬於當前終端的子程式,從而也就不會受到當前終端的 HUP 訊號的影響了。


比較而言,我更喜歡用setsid,簡單實用。當然,這裡看大家喜好即可,效果上差別不大。


相關文章