Shell
為什麼 SSH -t 不等待後台程序?
為什麼
ssh -t
不等待後台作業完成?例子:
ssh user@example 'sleep 2 &'
這按預期工作,因為 ssh 在 2 秒後返回,而
ssh user@example -t 'sleep 2 &'
不等待
sleep
完成並立即返回。誰能解釋這背後的原因?有沒有辦法讓
ssh -t
等待所有後台程序完成後再返回?我的案例是我用 啟動一個腳本
ssh -t
,這個腳本啟動幾個後台作業,這些作業在主腳本完成後應該保持活動狀態。ssh -t
到目前為止,這是不可能的。
如果沒有
-t
,則通過兩個管道sshd
獲取遠端 shell 的標準輸出(以及類似的子級sleep
)和標準錯誤(並且還通過另一個管道發送客戶端的輸入)。
sshd
確實等待啟動使用者登錄 shell 的程序,但在該程序終止後,等待 stdout 管道上的 eof (至少在 openssh 的情況下不是 stderr 管道)。當在管道的寫入端打開的任何程序都沒有打開文件描述符時,就會發生 eof,這通常僅在所有沒有將其 stdout 重定向到其他東西的程序都消失時才會發生。
使用時
-t
,sshd
不使用管道。相反,與遠端外殼及其子外殼的所有互動(stdin、stdout、stderr)都是使用一對偽終端完成的。使用偽終端對,用於
sshd
與主端進行互動,沒有類似的 eof 處理,雖然至少一些系統提供了替代方法來了解是否仍有 fds 程序對偽終端的從端開放(參見 @下面的 JdeBP 註釋),sshd
不使用它們,所以它只是等待它執行遠端使用者的登錄 shell 的程序終止,然後退出。在該退出時,pty 對的主端關閉,這意味著 pty 被銷毀,因此由從屬控制的程序將收到一個 SIGHUP(預設情況下會終止它們)。
編輯:最後一部分是不正確的,儘管最終結果是一樣的。請參閱@pynexj 的答案以正確描述究竟發生了什麼。