與 SSH 會話斷開連接會殺死您的程序嗎?
因此,假設我在啟動或任何其他可能長時間執行的命令後與 SSH 會話斷開
rsync
連接cp
。在我斷開連接後該命令會一直執行直到它完成還是它只是被殺死?一直在想這個。
2016年編輯:
此問答早於systemd v230 崩潰。從 systemd v230 開始,新的預設設置是殺死終止登錄會話的所有子節點,無論採取了哪些歷史上有效的預防措施來防止這種情況發生。可以通過設置來更改行為
KillUserProcesses=no
,/etc/systemd/logind.conf
或者使用 systemd 特定的機制在使用者空間中啟動守護程序來規避。這些機制超出了這個問題的範圍。下面的文字描述了傳統上事情在 UNIX 設計空間中的工作時間比 Linux 存在的時間更長。
他們會被殺死,但不一定會立即被殺死。這取決於 SSH 守護程序需要多長時間才能確定您的連接已失效。下面是一個較長的解釋,將幫助您了解它的實際工作原理。
當您登錄時,SSH 守護程序會為您分配一個偽終端並將其附加到您的使用者配置的登錄 shell。這稱為控制終端。你在那個時候正常啟動的每個程序,無論有多少層貝殼,最終都會將它的祖先追溯到那個貝殼。
pstree
您可以使用命令觀察這一點。當與您的連接關聯的 SSH 守護程序確定您的連接已失效時,它會向
SIGHUP
登錄 shell 發送一個掛斷信號 ( )。這會通知外殼您已經消失並且它應該開始自行清理。此時發生的事情是特定於 shell 的(在其文件頁面中搜尋“HUP”),但在大多數情況下,它會SIGHUP
在終止之前開始發送到與其關聯的正在執行的作業。反過來,這些程序中的每一個都會在收到該信號時執行它們配置為執行的任何操作。通常這意味著終止。如果這些工作有自己的工作,信號通常也會傳遞。在控制終端掛斷後倖存下來的程序要麼與終端(您在其中啟動的守護程序)解除關聯,要麼是使用前綴
nohup
命令呼叫的程序。(即“不要掛斷”)守護程序以不同的方式解釋 HUP 信號;由於他們沒有控制終端並且不會自動接收 HUP 信號,因此它被重新用作管理員的手動請求以重新載入配置。具有諷刺意味的是,這意味著大多數管理員直到很久很久以後才知道該信號對非守護程序的“掛斷”用法。這就是你閱讀這篇文章的原因!終端多路復用器是在斷開連接之間保持 shell 環境完整的常用方法。它們允許您以一種以後可以重新連接到它們的方式與您的 shell 程序分離,無論這種斷開是偶然的還是故意的。
tmux
並且screen
是更受歡迎的;使用它們的語法超出了您的問題範圍,但值得研究。有人要求我詳細說明 SSH 守護程序需要多長時間才能確定您的連接已失效。這是特定於 SSH 守護程序的每個實現的行為,但您可以指望它們在任何一方重置 TCP 連接時終止。如果伺服器嘗試寫入套接字並且 TCP 數據包未得到確認,這將很快發生,或者如果沒有嘗試寫入 PTY,則會緩慢發生。
在這種特殊情況下,最有可能觸發寫入的因素是:
- 一個程序(通常在前台)試圖寫入伺服器端的 PTY。(伺服器->客戶端)
- 使用者嘗試在客戶端寫入 PTY。(客戶端->伺服器)
- 任何形式的保活。預設情況下,這些通常不被客戶端或伺服器啟用,並且通常有兩種風格:應用程序級別和基於 TCP(即
SO_KEEPALIVE
)。Keepalives 相當於伺服器或客戶端不經常向另一端發送數據包,即使沒有任何其他理由寫入套接字。雖然這通常是為了避開那些過快連接超時的防火牆,但它具有額外的副作用,即當對方沒有更快地響應時,它會導致發件人注意到。TCP 會話的正常規則在這裡適用:如果客戶端和伺服器之間的連接中斷,但在問題期間雙方都沒有嘗試發送數據包,則連接將繼續存在,前提是雙方隨後都做出響應並接收到預期的 TCP序號。
如果一方已經確定套接字已失效,則效果通常是立竿見影的:sshd 程序將發送
HUP
並自行終止(如前所述),或者客戶端將通知使用者檢測到的問題。值得注意的是,僅僅因為一方認為對方已經死了,並不意味著對方已經得到了通知。連接的孤立端通常會保持打開狀態,直到它嘗試寫入它並超時,或者從另一端接收到 TCP 重置。(如果當時連接可用)此答案中描述的清理僅在伺服器注意到後才會發生。