Tmux

與 ssh 斷開連接時 tmux 會話被終止

  • August 5, 2020

摘要:我試圖弄清楚為什麼當我從 ssh 斷開連接時我的 tmux 會話會死掉

詳情

我在 Arch Linux 系統上安裝了 tmux。當我啟動一個 tmux 會話時,我可以從中分離,然後在 ssh 會話處於活動狀態時再次附加。但是如果我結束我的 ssh 會話,那麼 tmux 會話就會被終止。

我知道這不是正常行為,因為我有其他系統,即使 ssh 會話結束,tmux 會話也會繼續執行,並且我可以在建立新的 ssh 連接後附加到 tmux 會話。有問題的系統和正常工作的系統具有非常相似的配置,所以我不確定要檢查什麼。

我正在執行 tmux 1.9a 版。有問題的系統(我有 root 訪問權限)的 Linux 核心版本為 3.17.4-1,正常工作的系統的核心版本為 3.16.4-1-ARCH(我沒有 root 權限)系統)。我懷疑核心版本是問題的根源,這只是我注意到的一個區別。

我想我會問是否有人見過類似的問題並知道可能的解決方案。

導致問題的確切步驟是:

  1. ssh 到機器
  2. 執行tmux以啟動 tmux
  3. ctrl-B D分離(此時我可以重新連接tmux attach
  4. 關閉 ssh 會話(此時 tmux 會話被終止,當我在另一個終端以 root 身份登錄時,我已經能夠觀察到這一點)
  5. 重新連接 ssh 並執行tmux attach,我收到消息no sessions並執行tmux ls返回failed to connect to server: Connection refused。這是有道理的,因為服務沒有執行。對我來說沒有意義的是為什麼當我從 ssh 會話斷開連接時它在第 4 步中被殺死。

數據失去:

作為對其中一條評論的回應,我使用 strace 來查看系統呼叫 tmux 伺服器程序所做的事情。看起來當我退出我的 ssh 會話(通過鍵入exit或 with ctrl-d)時,tmux 程序被殺死了。這是 strace 輸出的最後一部分的片段。

poll([{fd=4, events=POLLIN}, {fd=11, events=POLLIN}, {fd=6, events=POLLIN}], 3, 424) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=1, si_uid=0} ---
sendto(3, "\17", 1, 0, NULL, 0)         = 1
+++ killed by SIGKILL +++

我將其與 tmux 正常工作的不同系統進行了比較,在該系統上,即使在我退出後,tmux 程序也會繼續執行。所以根本原因似乎是當我關閉 ssh 會話時 tmux 程序正在終止。我需要花一些時間來解決這個問題以找出原因,但我想我會更新我的問題,因為 strace 建議很有用。

理論

包括 systemd 在內的一些 init 系統提供了殺死屬於該服務的所有程序的功能。該服務通常啟動一個程序,該程序通過分叉創建更多程序,這些程序也可以這樣做。所有此類過程通常都被視為服務的一部分。在 systemd 中,這是使用cgroups完成的。

在 systemd 中,預設情況下,當服務停止時,屬於服務的所有程序都會被殺死。SSH 伺服器顯然是服務的一部分。當您連接到伺服器時,SSH 伺服器通常會分叉,新程序會處理您的 SSH 會話。通過從 SSH 會話程序或其子程序分叉,其他伺服器端程序將啟動,包括您的screentmux

Killmode 和套接字啟動

可以使用該KillMode指令更改預設行為。上游項目不 AFAIK 包含任何.service文件,因此這些文件因分佈而異。通常有兩種方法可以在您的系統上啟用 SSH。ssh.service一個是在網路上維護一個長時間執行的 SSH 守護程序的經典之作。另一種是通過套接字啟動處理,ssh.socket然後啟動sshd@.service它只執行一個單一的 SSH 會話。

解決方案

如果您的程序在會話結束時被終止,則可能是您正在使用套接字啟動,並且當 systemd 注意到 SSH 會話程序退出時,它會被 systemd 終止。在這種情況下,有兩種解決方案。ssh.service一種是通過使用而不是來避免使用套接字啟動ssh.socket。另一種是設置KillMode=processService.ssh@.service

KillMode=process設置也可能對 classic 有用ssh.service,因為它可以避免在伺服器停止或重新啟動時殺死 SSH 會話程序或screentmux程序。

未來筆記

這個答案顯然獲得了一定程度的普及。雖然它適用於 OP,但由於systemd-logind 開發或配置,它可能會在未來不適用於某人。如果您遇到與此答案中描述不同的行為,請查看有關登錄會話的文件。

引用自:https://unix.stackexchange.com/questions/171503