获取 ssh 转发信号

获取 ssh 转发信号

我希望能够通过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。

还有别的办法吗?

编辑:

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

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 为我指明了正确的方向。

答案1

简短回答:

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 信号之后将不会有任何标准输出。

答案2

我尝试了所有的解决方案,这是最好的:

ssh host "sleep 99 < <(cat; kill -INT 0)" <&1

https://stackoverflow.com/questions/3235180/starting-a-process-over-ssh-using-bash-and-then-killing-it-on-sigint/25882610#25882610

答案3

解决方案演变为https://www.gnu.org/software/parallel/parallel_design.html#The-remote-system-wrapper

$SIG{CHLD} = sub { $done = 1; };
$pid = fork;
unless($pid) {
    # Make own process group to be able to kill HUP it later
    setpgrp;
    exec $ENV{SHELL}, "-c", ($bashfunc."@ARGV");
    die "exec: $!\n";
}
do {
    # Parent is not init (ppid=1), so sshd is alive
    # Exponential sleep up to 1 sec
    $s = $s < 1 ? 0.001 + $s * 1.03 : $s;
    select(undef, undef, undef, $s);
} until ($done || getppid == 1);
# Kill HUP the process group if job not done
kill(SIGHUP, -${pid}) unless $done;
wait;
exit ($?&127 ? 128+($?&127) : 1+$?>>8)

答案4

----- 命令.sh

#! /bin/sh
trap 'trap - EXIT; kill 0; exit' EXIT
(sleep 1000;echo f) &
read ans

----- 在本地终端上

sleep 864000 | ssh -T server command.sh > foo

相关内容