ssh 终止后,ssh 命令在其他系统上意外继续

me_*_*and 11 ssh rhel openssh sshd

我正在运行以下命令,并监视另一个系统上的输出文件:

ssh $ip_address 'for n in 1 2 3 4 5; do sleep 10; echo $n >>/tmp/count; done'
Run Code Online (Sandbox Code Playgroud)

如果我使用^C或仅通过终止我登录的终端来终止ssh 命令,我希望远程命令也终止。但是,这不会发生:/tmp/count无论如何都会获取所有数字 1-5,并ps -ejH显示 shell 及其sleep子项继续运行。

这是预期的行为吗,是否在任何地方都有记录?我可以禁用它吗?通过阅读,我希望必须使用 nohup 显式启用这种行为,而不是让它成为默认值。

我查看了 ssh 和 sshd 的手册页,但没有发现任何明显的内容,Google 向我指出了打开此行为的说明,而不是关闭它的说明。

我正在运行 Red Hat Enterprise Linux 6.2,两个系统上都有 root 登录名和 bash shell。

Gil*_*il' 11

uther 的回答告诉您分配一个终端,但没有解释原因。原因并非特定于 ssh,而是信号生成和传播的问题。我邀请您阅读什么导致发送各种信号?更多背景。

在远程主机上,有两个相关的进程:

  • ssh 守护进程 ( sshd) 的一个实例,它将远程程序的输入和输出中继到本地终端;
  • 一个运行该for循环的外壳。

shell 可以在到达循环末尾或遇到致命错误时自然死亡,也可以在收到信号时死亡。问题是,为什么shell会收到信号?

如果远程 shell 连接到sshd管道上,这是在ssh命令行上指定命令时发生的情况,那么如果退出并且 shell 尝试写入管道,它将死于SIGPIPEsshd。只要 shell 没有写入管道,它就不会收到 SIGPIPE。在这里,shell 永远不会向其标准输出写入任何内容,因此它可以永远存在。

您可以将-t选项传递给 ssh,以告诉它模拟远程端的终端并在此终端中运行指定的命令。然后,如果 SSH 客户端消失,则sshd关闭连接并退出,从而破坏终端。当终端设备消失时,其中运行的任何进程都会收到SIGHUP。因此,如果您kill终止SSH 客户端(使用,或通过关闭客户端正在运行的终端),远程 shell 将被 SIGHUPped。

如果您传递该-t选项,SSH 还会中继SIGINT。如果按Ctrl+ C,则远程 shell 会收到一个 SIGINT。