获取 ssh 转发信号

Ole*_*nge 24 ssh remote signals tty

我希望能够通过 ssh 发送信号(SIGINT 是最重要的)。

这个命令:

ssh server "sleep 1000;echo f" > foo
Run Code Online (Sandbox Code Playgroud)

将在服务器上开始睡眠,并在 1000 秒后将 'f\n' 放在我本地机器上的文件 foo 中。如果我按 CTRL-C(即向 ssh 发送 SIGINT),它将终止 ssh,但不会终止远程服务器上的 sleep。我希望它杀死远程服务器上的睡眠。

所以我试过:

ssh server -t "sleep 1000;echo f" > foo
Run Code Online (Sandbox Code Playgroud)

但如果 stdin 不是终端,我会收到此错误:

Pseudo-terminal will not be allocated because stdin is not a terminal.
Run Code Online (Sandbox Code Playgroud)

然后 SIGINT 仍然没有转发。

所以我试过:

ssh server -t -t "sleep 1000;echo f" > output
Run Code Online (Sandbox Code Playgroud)

但是 foo 中的输出不是 'f\n' 而是 'f\r\n' 这在我的情况下是灾难性的(因为我的输出是二进制数据)。

在上面我使用“sleep 1000;echo f”,但实际上它是由用户提供的,因此它可以包含任何内容。然而,如果我们可以让它适用于“sleep 1000;echo f”,我们很可能让它适用于所有现实情况。

我真的不关心在另一端获得伪终端,但我一直无法找到任何其他方式让 ssh 转发我的 SIGINT。

还有其他方法吗?

编辑:

用户可以给出从 stdin 读取二进制数据的命令,例如:

seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo
Run Code Online (Sandbox Code Playgroud)

用户可以给出 CPU 密集型的命令,例如:

ssh server "timeout 1000 burnP6"
Run Code Online (Sandbox Code Playgroud)

编辑2:

似乎对我有用的版本是:

your_preprocessing |
  uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - |
your_command |
  uuencode a" | uudecode -o - |
your_postprocessing
Run Code Online (Sandbox Code Playgroud)

感谢 digital_infinity 为我指明了正确的方向。

dig*_*ity 13

简短的回答:

ssh -t fs "stty isig intr ^N -echoctl ; trap '/bin/true' SIGINT; sleep 1000; echo f" > foo
Run Code Online (Sandbox Code Playgroud)

并按 CTRL+N 停止程序。

长解释:

  1. 您必须使用stty选项intr来更改您的服务器或本地中断字符,以免相互冲突。在上面的命令中,我将服务器中断字符更改为 CTRL+N。您可以更改本地中断字符,而无需更改服务器的中断字符。
  2. 如果您不希望中断字符出现在您的输出(和任何其他控制字符)中,请使用stty -echoctl.
  3. 您必须确保在 sshd 调用的服务器 bash 上打开了控制字符。如果不这样做,您可能会在注销后最终发现进程仍然存在。stty isig
  4. 你实际上用空语句捕捉SIGINT信号trap '/bin/true' SIGINT。如果没有陷阱,您将在 SIGINT 信号之后没有任何标准输出。