使用 & 和輸出重定向而不是 nohup 是否安全?
有很多關於 nohup 的堆棧交換答案,這裡有幾個供參考:
如果您已經使用 ‘&’ 分叉,什麼時候需要 ’nohup’?
規範的答案似乎是,使用 nohup 可以防止程序在終端關閉時結束,所以像這樣的命令:
nohup mycommand >& mycommand_output.txt &
下次我登錄時仍然會執行,它會保存輸出,以便我以後檢查。
但是如果我保存了一些擊鍵:
mycommand >& mycommand_output.txt &
下次登錄時仍然在執行。
它與 nohup 不同,因為我可以用
kill -HUP
. 當我重新登錄時,ps -x
說程序的 TTY 是 now?
,所以程序還沒有連接到終端。為什麼當我退出 shell 時程序沒有停止?
如果我不使用 nohup,我可以安全地假設我的流程不會結束嗎?
萬一這很重要,我目前的環境涉及從 Ubuntu 機器通過 SSH 連接到 Debian 機器。
如果我不使用 nohup,我可以安全地假設我的流程不會結束嗎
不會。如果終端掛斷並且它有一個互動式 shell 作為會話負責人,shell 將獲得一個 SIGHUP 並將其重新發送到它尚未被拒絕的工作。
huponexit
如果 shell 自願退出,如果該選項打開,它將向其作業發送 SIGHUP 。如果 shell 自願退出並且擁有的作業被停止,bash 將使用 SIGTERM 殺死它們(不確定這是否是標準行為)。
如果 shell 自願退出並且有停止的不承認的作業,終端驅動程序將使用 SIGHUP 殺死它們(這絕對是標準規定的)。
所以你仍然可以在各種情況下被 SIGHUP 殺死。
也就是說,通過查看http://src.gnu-darwin.org/src/usr.bin/nohup/nohup.c.html上的 nohup 原始碼,它似乎在純 shell 中或多或少是可行的:
nohup_sh() ( set -e if [ -t 1]; then exec >> nohup.out || exec >> "$HOME/nohup.out" fi if [ -t 0 ]; then exec 0</dev/null fi if [ -t 2 ]; then exec 2>&1 fi trap '' HUP #ignore SIGHUP (inheritable) set -m || : #to prevent SIGINT and SIGQUIT from being ignored #(probably not needed, but the nohup binary won't ignore them, unlike # & without set -m) command "$@" & )
您可能不需要 之外的額外內容
trap '' HUP
,儘管如果該作業嘗試寫入斷開連接的終端(這是重定向阻止的),它將獲得 SIGPIPE。
為什麼當我退出 shell 時程序沒有停止?
可能是因為你告訴了shell
disown
。或者,您可能沒有使用互動式作業控制 shell 作為會話領導程序。世界在 1980 年代確定的會話+程序組組合模型的工作方式如下:有一個會話負責人程序。這就是在終端掛斷時從終端線路規程中獲取掛斷信號的原因。預計會放大該信號,本身將信號發送到它產生的所有“工作”。互動式作業控制外殼將執行此操作;大多數其他程序不期望有會議負責人的職責,也不會。
nohup
當會話領導者向它們發送掛斷信號時,使用使這些“作業”中的程序忽略掛斷信號。Usingdisown
使會話領導者 shell 忘記了一項工作,因此它從一開始就不會向它發送掛斷信號。如果我不使用 nohup,我可以安全地假設我的流程不會結束嗎?
不會。如果它們沒有被
disown
ed,那麼會話領導者互動式作業控制 shell 程序將向它們發送掛斷信號。此外:systemd 的人試圖實現與核心會話等效的使用者空間機制,但他們對此有點耳熟能詳,這在(某些)systemd 作業系統上引入了進一步的複雜性。在 systemd session hangup 而不是
SIGHUP
像核心的 line 規則那樣只發送給 session leader,它們錯誤地發送SIGTERM
給所有程序,錯誤地表示shutdown而不是hangup。
SIGTERM
在標準會話+程序組模型中,系統關閉時,所有程序當然會發生什麼;這會殺死所有程序,包括不承認的程序和忽略掛斷信號的程序。當然,它也會殺死你既沒有被disown
編輯也沒有被編輯nohup
的程序。進一步閱讀