連接關閉時如何遠端終止稱為“tail -f”?
我剛剛注意到,如果我執行
ssh user@remote_host tail -f /some/file
,tail -f /some/file
即使 ssh 連接關閉,也會繼續在 remote_host 上執行!因此,在多次連接和斷開連接後,執行次數
tail -f /some/file
會增加。tail -f
關閉 ssh 連接時如何實際終止?
在
ssh host tail -f file
客戶端通過TCP 連接
ssh
連接到sshd
伺服器。執行時將其標準輸出重定向到管道。讀取來自管道另一端的內容並將其封裝在 sshd 協議中以發送給客戶端。(使用,stdout 將直接是套接字,但添加了加密並且能夠在單個 TCP 連接上多路復用多個流(例如埠/代理/X11/隧道重定向,stderr),因此必須求助於管道)。host``sshd``tail -f``sshd``ssh``rshd``tail``sshd
當您按下 CTRL-C 時,會向
ssh
客戶端發送一個 SIGINT。這導致ssh
死亡。死後 TCP 連接關閉。因此, onhost
也會sshd
死掉。tail
沒有被殺死,但它的標準輸出現在是另一端沒有閱讀器的管道。因此,下次它向其標準輸出寫入內容時,它將收到一個 SIGPIPE 並死掉。在:
ssh -t host 'tail -f file'
除了不是使用管道,而是通過偽終端進行通信之外
sshd
,這是同一件事。的 stdout 是一個從屬偽終端(如),主端的任何寫入(可能由 tty 行規則修改)由客戶端封裝並發送給客戶端。tail``tail``/dev/pts/12``tail``read``sshd``ssh
在客戶端,使用
-t
將ssh
終端置於raw
模式。特別是,這會禁用終端規範模式和終端信號處理。因此,當您按下 時
Ctrl+C
,客戶端的終端線路規則不會向ssh
作業發送 SIGINT,而是通過^C
連接將字元發送到遠端終端的主端sshd
並將其sshd
寫入。^C
並且遠端終端的線路規則發送SIGINT
到tail
。tail
然後死掉,sshd
退出並關閉連接並ssh
終止(如果它不忙於埠轉發或其他)。此外,
-t
如果ssh
客戶端死亡(例如,如果您輸入~.
),則連接將關閉並sshd
終止。結果,一個 SIGHUP 將被發送到tail
.現在,請注意使用
-t
有副作用。例如,使用預設終端設置,\n
字元被轉換為\r\n
,並且可能會發生更多事情,具體取決於遠端系統,因此stty -opost
如果該輸出不是用於的,您可能希望在遠端主機上發出(禁用輸出後處理)一個終端:$ ssh localhost 'echo x' | hd 00000000 78 0a |x.| 00000002 $ ssh -t localhost 'echo x' | hd 00000000 78 0d 0a |x..| 00000003 $ ssh -t localhost 'stty -opost; echo x' | hd 00000000 78 0a |x.| 00000002
-t
使用/的另一個缺點-tt
是 stdout 和 stderr 在客戶端上沒有區別。遠端命令的 stdout 和 stderr 都將寫入ssh
客戶端的 stdout:$ ssh localhost ls /x | wc -l ls: cannot access /x: No such file or directory 0 $ ssh -t localhost ls /x | wc -l 1