Ssh

獲取 ssh 轉發信號

  • March 21, 2020

我希望能夠通過 ssh 發送信號(SIGINT 是最重要的)。

這個命令:

ssh server "sleep 1000;echo f" > foo

將在伺服器上開始睡眠,並在 1000 秒後將 ‘f\n’ 放入我本地電腦上的文件 foo 中。如果我按 CTRL-C(即向 ssh 發送 SIGINT),它將終止 ssh,但不會終止遠端伺服器上的睡眠。我希望它殺死遠端伺服器上的睡眠。

所以我嘗試了:

ssh server -t "sleep 1000;echo f" > foo

但是,如果 stdin 不是終端,我會收到此錯誤:

Pseudo-terminal will not be allocated because stdin is not a terminal.

然後 SIGINT 仍然沒有轉發。

所以我嘗試了:

ssh server -t -t "sleep 1000;echo f" > output

但是 foo 中的輸出不是 ‘f\n’ 而是 ‘f\r\n’ 這在我的情況下是災難性的(因為我的輸出是二進制數據)。

在上面我使用“sleep 1000;echo f”,但實際上它是由使用者提供的,因此它可以包含任何內容。但是,如果我們可以讓它適用於“sleep 1000;echo f”,我們很可能讓它適用於所有現實情況。

我真的不關心在另一端獲得一個偽終端,但我一直無法找到任何其他方式讓 ssh 轉發我的 SIGINT。

還有其他方法嗎?

編輯:

使用者可以給出從標準輸入讀取二進制數據的命令,例如:

seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo

使用者可以給出 CPU 密集型命令,例如:

ssh server "timeout 1000 burnP6"

編輯2:

似乎對我有用的版本是:

your_preprocessing |
 uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - |
your_command |
 uuencode a" | uudecode -o - |
your_postprocessing

感謝 digital_infinity 為我指明了正確的方向。

簡短的回答:

ssh -t fs "stty isig intr ^N -echoctl ; trap '/bin/true' SIGINT; sleep 1000; echo f" > foo

並按 CTRL+N 停止程序。

長解釋:

  1. 您必須使用stty選項intr來更改您的伺服器或本地中斷字元以不相互衝突。在上面的命令中,我將伺服器中斷字元更改為 CTRL+N。您可以更改本地中斷字元並保留伺服器的中斷字元而不做任何更改。
  2. 如果您不希望中斷字元出現在您的輸出(和任何其他控製字元)中,請使用stty -echoctl.
  3. 您必須確保在 sshd 呼叫的伺服器 bash 上打開了控製字元。如果你不這樣做,你最終可能會在註銷後程序仍然掛起。stty isig
  4. 你實際上用空語句擷取SIGINT信號。trap '/bin/true' SIGINT如果沒有陷阱,您將不會在 SIGINT 信號結束後獲得任何標準輸出。

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