Shell
nohup、disown 和 & 之間的區別
之間有什麼區別
$ nohup foo
和
$ foo &
和
$ foo & $ disown
讓我們首先看看如果一個程序從一個互動式外殼(連接到終端)啟動而沒有
&
(也沒有任何重定向)會發生什麼。所以讓我們假設你剛剛輸入foo
:
- 正在執行的程序
foo
被創建。- 該程序從 shell 繼承 stdin、stdout 和 stderr。因此它也連接到同一個終端。
- 如果 shell 收到 a
SIGHUP
,它也會向SIGHUP
程序發送 a (這通常會導致程序終止)。- 否則,shell 會等待(被阻塞),直到程序終止或停止。
現在,讓我們看看如果將程序置於後台會發生什麼,即鍵入
foo &
:
正在執行的程序
foo
被創建。該程序從 shell 繼承 stdout/stderr(因此它仍然寫入終端)。
該程序原則上也繼承了標準輸入,但是一旦它嘗試從標準輸入中讀取,它就會停止。
它被放入 shell 管理的後台作業列表中,這尤其意味著:
- 它與(作業編號在哪裡)一起列出
jobs
並且可以訪問。%n``n
- 可以使用 將其轉換為前台作業
fg
,在這種情況下,它會繼續執行,就好像您不會使用&
它一樣(如果它由於嘗試從標準輸入讀取而停止,它現在可以繼續從終端讀取)。- 如果 shell 收到 a
SIGHUP
,它也會向SIGHUP
程序發送 a 。根據 shell 和可能為 shell 設置的選項,當終止 shell 時,它也會向SIGHUP
程序發送一個。現在
disown
從 shell 的作業列表中刪除作業,因此上面的所有子點不再適用(包括SIGHUP
由 shell 發送的程序)。但是請注意,它仍然連接到終端,所以如果終端被破壞(如果它是一個 pty,例如由xterm
or創建的那些ssh
,並且通過關閉 xterm 或終止SSH連接來終止控製程序,則可能發生這種情況) ,程序一旦嘗試從標準輸入讀取或寫入標準輸出就會失敗。
nohup
另一方面,有效地將程序與終端分離:
- 它關閉標準輸入(程序將無法讀取任何輸入,即使它在前台執行。它不會停止,但會收到錯誤程式碼或
EOF
)。- 它將標準輸出和標準錯誤重定向到文件
nohup.out
,因此如果終端失敗,程序寫入標準輸出不會失敗,因此無論程序寫入什麼都不會失去。- 它阻止程序接收一個
SIGHUP
(因此名稱)。請注意,
nohup
它不會從 shell 的作業控制中刪除程序,也不會將其置於後台(但由於前台nohup
作業或多或少無用,您通常會使用 將其置於後台&
)。例如,與 with 不同disown
,shell 仍然會告訴您 nohup 作業何時完成(當然,除非 shell 之前終止)。所以總結一下:
&
將作業置於後台,也就是說,使其阻止嘗試讀取輸入,並使 shell 不等待其完成。disown
從 shell 的作業控制中刪除該程序,但仍將其連接到終端。結果之一是外殼不會向它發送SIGHUP
. 顯然,它只能應用於後台作業,因為在前台作業執行時無法進入。nohup
斷開程序與終端的連接,將其輸出重定向nohup.out
到SIGHUP
. 效果之一(命名)是該程序不會收到任何 sentSIGHUP
。它完全獨立於作業控制,原則上也可以用於前台作業(儘管這不是很有用)。