SSH会话中的Ctrl-C处理


20

当我启动执行长时间运行的命令的SSH会话时,使用Ctrl+ C(SIGINT)处理会发生什么?

我可以看到SSH会话已关闭,但是我不确定谁先获得了SIGINT:是吗...

  1. 远程长时间运行的命令?也就是说,(a)调用远程命令中的信号处理程序并停止远程命令,(b)生成它的外壳程序检测到命令已停止,并且也停止(c)远程sshd检测到外壳程序已停止,所以它关闭了连接

    要么

  2. 本地ssh接收信号,并关闭连接。

我认为(1)正在发生,但想确定。

在这种情况下,我也不确定SIGINT的外壳处理会发生什么情况。例如,如果我...

ssh remote 'while true ; do sleep 1 ; date ; done'

Ctrl+ C,然后断开远程连接。有没有一种方法可以在Ctrl+ 之后仍然有效的shell下运行远程命令C?也就是说,在这种情况下,停止循环并允许我继续在远程Shell上工作吗?


3
通过键入ctrl-C生成的SIGINT将使非交互式ssh(ssh remote command相对于ssh remote)被杀死(在本地)。远程端可能会(取决于操作系统)一直运行,直到尝试读取或写入关闭的套接字为止。如果要将包括ctrl-C在内的所有击键都传递给遥控器,请使用ssh remote
Mark Plotnick

@MarkPlotnick:好的,马克-如果您在下面添加您的回答作为答案,我会接受的。。。在我自己的测试中,我确认遥控器没有收到任何信号。
ttsiodras 2014年

Answers:


23

ssh可以用几种不同的方式调用,每种方式对终端启动信号(如)的处理略有不同Ctrl-C

  • ssh remotehost将在上运行一个交互式会话remotehost。在客户端,ssh将尝试将stdin使用的tty设置为“原始”模式,而sshd在远程主机上,将分配一个伪tty并将您的shell作为登录shell运行(例如-bash)。

    设置原始模式意味着将通常会发送信号的字符(例如Ctrl-CCtrl-\)插入到输入流中。ssh会将这些字符原样发送到远程主机,它们很可能会在其中发送SIGINT或SIGQUIT,并且通常会杀死所有命令并将您返回到远程主机上的Shell。只要远程外壳处于活动状态,ssh连接将保持活动状态。

  • ssh -t remotehost command args ...remotehost像上面一样在上运行一个交互式会话,但在远程端除外your_shell -c "command args ..."。如上所述,如果键入Ctrl-C,它将被发送到远程主机,该命令可能会收到SIGINT并立即退出,然后远程外壳程序将退出。遥控器sshd然后关闭连接,并ssh报告Connection to remotehost closed.

  • ssh remotehost command args ...将在上运行非交互式会话remotehost。在客户端侧,ssh设置TTY到原始模式(当然,除了在密码或口令阅读)。如果输入Ctrl-Cssh将发送SIGINT并立即终止,甚至不发出Connection to remotehost closed消息。

    这些your_shell -c "command args ..."进程可能仍将在远程主机上运行。它们要么自行退出,要么一个进程尝试将数据写入到现在关闭的ssh套接字,这将导致(通常)致命的SIGPIPE信号发送给它。


1
从技术上讲,远程命令不会直接写入套接字。它的标准输出是管道。另一端的sshd读取数据,对其进行加密,然后通过套接字发送。最终结果是一样的。该命令将获得一个sigpipe,因为在客户端断开连接时该管道已消失。
斯特凡Chazelas

@StéphaneChazelas谢谢,我将编辑答案进行更正。
Mark Plotnick
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.