题 当SSH连接中断时,为什么控制台有时会永远挂起?


我见过这么多游戏机(在Linux,Mac上......),并且在许多不同的网络中有很多不同的机器。我永远无法确定究竟的原因,为什么会发生这种情况:您只需通过SSH登录计算机即可。如果由于某种原因连接断开(为简单起见,假设网络电缆被拉出),那么有时控制台会永远挂起 - 在其他时候,它只是退出到父shell。

发生这种情况时非常烦人(例如,你丢失了命令历史记录。)是否有可能强制退出的机密键盘快捷键(Ctrl-C或Ctrl-D不起作用)?无论如何,这个随机“错误”在所有实现中的原因是什么?


74
2018-06-22 18:12




这个话题似乎很合适 MOSH (移动外壳)处理连接失败,包括漫游(IP更改)和其他东西。 - Ciprian Tomoiagă


答案:


有一个“秘密”键盘快捷键强制退出:〜)从冻结的会话中,按顺序点击这些键: 输入 波形符号(仅在换行符之后)被ssh客户端识别为转义序列,并且句点告诉客户端终止它的业务而没有进一步的麻烦。

通信问题上的长时间挂起行为不是一个错误,SSH会话正在停止,希望对方会回来。如果网络中断,有时甚至几天后您就可以恢复SSH会话。当然,你可以明确告诉它放弃并按照上面的顺序消亡。您还可以执行各种操作,例如在客户端中设置保持活动超时,以便在一段时间内没有活动链接时,它会自行关闭,但默认行为是保持为尽可能连接!

编辑: 这个中断密钥的另一个有用的应用是引起本地ssh客户端的注意,并让它回到本地shell一分钟 - 从你的历史记录中得到一些东西 - 然后forground继续远程工作。 输入  Ctrl键+ž 然后将ssh客户端发送到本地shell的后台作业队列 fg 正常回来。

编辑: 处理嵌套的SSH会话时,您可以添加多个波形符,以便仅断开链中的一个SSH会话,但保留其他会话。例如,如果你嵌套在3个级别中,(即你从local-> Machine1-> Machine2-> Machine3), 输入 会让你回到你当地的会议, 输入 会留在Machine1,和 输入 将离开你在Machine2。这也适用于其他转义序列,例如暂时将ssh会话移动到后台。以上适用于任何级别的嵌套,只需添加更多波形符。

最后,你可以使用 输入 打印可用转义命令的帮助菜单。

TL; DR - 支持的转义命令 支持的转义序列:

 ~.   - terminate connection (and any multiplexed sessions)
 ~B   - send a BREAK to the remote system
 ~C   - open a command line
 ~R   - request rekey
 ~V/v - decrease/increase verbosity (LogLevel)
 ~^Z  - suspend ssh
 ~#   - list forwarded connections
 ~&   - background ssh (when waiting for connections to terminate)
 ~?   - this message
 ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

121
2018-06-22 18:15



+1用于了解头部射击sshd的dodecatouple-secret-probation密码。你是否以同样的方式找到了它(错误的拼写 ~/.somethingorother 击中后输入)? - voretaq7
@ voretaq7:不,我不是那么聪明,但当有人确实让我知道时,我去了 “真的吗?那就是那些时候发生的事情,我的外壳刚刚变成了BANG!我打字的时候没有理由?”。这不是一个常见的序列,除了你提到的错误类型,但它可能发生。 - Caleb
因此,“秘密”意味着“在手册页中”。 - larsks
虽然许多人不知道这一点,但在平面视图中这真的是一个秘密。 man ssh 涵盖了这一点 ESCAPE CHARACTERS 部分。 ~. (断开连接)和 ~^Z (背景ssh)非常方便。 - Stefan Lasiewski
当然它在手册页:)我只使用了秘密这个词,因为OP做了,而我在脸颊上使用舌头。这个功能的问题是人们不知道在哪里寻找它,他们希望控制字符和这样的信号成为shell的一部分。一旦你知道在哪里看,甚至要问什么,当然它就在那里。 - Caleb


SSH提供了一个保持活动的设施。将以下内容添加到您的本地 ~/.ssh/config (如果它不存在则创建):

ServerAliveInterval 15
ServerAliveCount 3

此设置将建立通过安全隧道每15秒发送一次保持活动信号。连续三次失败后,SSH客户端将退出。

请注意,在某些系统上,它需要是:

ServerAliveInterval 15
ServerAliveCountMax 3

取自ask.ubuntu上的这个答案: https://askubuntu.com/a/29967/30266


10
2018-01-19 08:44





它挂起的事实是TCP的功能,而不是SSH。除非TCP使用连接不再存在的连接通知应用程序,否则应用程序无法知道TCP会话/连接已被切断。从每个主机的角度来看,TCP会话仍然处于Established状态,没有什么可说的,除了RST或者对TCP keepalive数据包缺乏响应之外,长空闲(没有数据流)会话是无效的(并非普遍实施)。这对我来说似乎不是SSH中的错误,我期待这种行为。


8
2018-06-22 19:49





如果连接正确挂起,则在发出按键之前连接已挂起时,任何魔术按键都无法通过。您可以告诉客户端终止,但这不会影响服务器端保留(或不保留)的历史记录。

虽然这实际上没有回答这个问题,但它可能有助于减少连接挂起的影响:当我正在远程工作时(甚至通常在我不工作时)我会通过 screen (有或没有 byobu 包装器取决于它的可用性)所以如果有任何类型的连接丢弃,我的会话及其所有历史记录将保留并在我重新连接时保留的状态下可用。


5
2018-06-22 18:18



您对屏幕的建议很好,但第一位实际上不适用于该问题。您不需要将密钥传递到远程端,您只需将它们传递给LOCAL ssh客户端即可! OP希望他的本地贝壳回归包括历史。 SSH接管它并且不响应正常的中断序列,如CTRL-C,因为它传递了那些。有一种方法可以通过并终止本地客户端,请参阅我的回答。如果再次登录,通常会保留本地历史记录,具体取决于shell配置。 - Caleb
@Caleb:专门提到丢失历史记录的问题,命令历史记录存储在服务器端。告诉服务器执行与历史记录不同的任何事情,以便向服务器发送消息,告诉它执行与历史记录不同的操作。当然有一些方法可以让bash(以及其他一些shell)立即记录历史记录,而不是将它们收集到RAM中,直到用户正确存在shell为止。 exit/logout 这将解决历史问题而不使用 screen。 - David Spillett