我已经在许多控制台(在Linux,Mac等上)以及在许多不同网络中的许多不同机器上看到了这一点。我永远无法查明发生这种情况的确切原因:您要做的就是通过SSH登录到计算机。如果连接由于某种原因而中断(为简单起见,假设网络电缆被拔出),则有时控制台会永远挂起-在其他时候,它仅在父shell处退出。

所以在发生这种情况时会很烦恼(例如,您丢失了命令历史记录。)也许存在秘密的键盘快捷键可以强制退出(Ctrl-C或Ctrl-D不起作用)?那么,在所有实现中出现此随机“错误”的原因是什么?

评论

提到Mosh(移动Shell)似乎很合适,它可以很好地处理连接失败,包括漫游(更改IP)和其他问题。

#1 楼

有一个“秘密”键盘快捷键可以强制退出:〜)从冻结的会话中,依次按以下键:Enter〜。代号(仅在换行符之后)被ssh客户端识别为转义序列,并且句点告诉客户端终止其业务,而无需多做。

关于通信问题的长期保留行为是这不是错误,SSH会话正在进行中,希望另一端回来。如果网络中断,有时甚至几天后,您就可以恢复SSH会话。当然,您可以明确地告诉它放弃并死于上述顺序。您还可以执行多种操作,例如在客户端中设置保持活动超时,这样,如果客户端在一定时间内没有活动链接,它将自行关闭,但是默认行为是保持请尽可能连接!您的历史记录-然后将其保留下来以继续远程工作。输入〜Ctrl + Z将ssh客户端发送到本地shell的后台作业队列,然后像往常一样fg将其取回。

编辑:在处理嵌套SSH会话时,您可以添加多个波浪号字符只能中断链中的一个SSH会话,而保留其他会话。例如,如果您嵌套在3个级别中(即您从local-> Machine1-> Machine2-> Machine3 ssh),请输入〜。将使您返回本地会话,请输入~~。将把您留在Machine1中,然后输入~~~。将您留在Machine2中。这也适用于其他转义序列,例如将ssh会话暂时移至后台。上面的方法适用于任何级别的嵌套,只需添加更多代字号即可。

最后,您可以使用Enter〜?打印可用转义命令的帮助菜单。

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.)


评论


+1表示知道在头部射击sshd的十二度秘密机密密码。您是否以与我相同的方式找到了它(打Enter键后输入〜/ .somethingorother错了)?

–voretaq7
2011年6月22日18:22



@ voretaq7:不,我不是那么聪明,但是当有人向我提示时,我说:“真的吗?那么这就是我的shell刚爆炸!除了您提到的错误类型以外,这不是一个常见的序列,但是可能会发生。

–卡莱布
2011年6月22日在18:34

其中“秘密”表示“在手册页中”。

–幼虫
2011年6月22日19:05

尽管许多人对此一无所知,但从实际情况看,这确实是一个秘密。 man ssh在ESCAPE CHARACTERS部分中对此进行了介绍。 〜。 (断开连接)和〜^ Z(背景ssh)非常方便。

– Stefan Lasiewski
2011年6月22日19:56

当然,它在手册页中:)我只用了secret一词,因为OP用过了,而且我在脸颊上用了舌头。此功能的问题在于,人们不知道在哪里寻找它,他们期望控制字符和此类信号成为外壳等的一部分。一旦您知道在哪里看甚至要问什么,当然就在那里。

–卡莱布
2011年6月22日20:17



#2 楼

SSH提供了保持活动的功能。将以下内容添加到本地~/.ssh/config(如果不存在则创建):隧道。连续三个失败后,SSH客户端将退出。

请注意,在某些系统上(包括macOS 10.14),它需要是:

ServerAliveInterval 15
ServerAliveCount 3


在ask.ubuntu上从此答案中摘录:https://askubuntu.com/a/29967/30266

#3 楼

它挂起的事实是TCP的功能,而不是SSH。除非TCP使用连接通知应用程序该连接不再存在,否则该应用程序无法知道TCP会话/连接已断开。从每个主机的角度来看,TCP会话仍处于“已建立”状态,无话可说,长时间的空闲(无数据流)会话除了RST或对TCP Keepalive数据包没有响应(这是无效的)外都是无效的。尚未普遍实施)。对我来说,这似乎不是SSH中的错误,我希望这种行为。

#4 楼

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

虽然这实际上并不能回答问题,但可能有助于减轻服务器端的影响。连接挂起:当我在远程工作时(甚至通常在我不工作时),我会遍历screen(有无byobu包装器,具体取决于它的可用性),以便在存在任何连接时都断开会话它的历史记录已保存,并且在我重新连接时保留了它的状态。

评论


您关于屏幕的建议很好,但实际上第一点不适用于此问题。您不需要将密钥传递到远程端,只需要将它们传递到LOCAL ssh客户端! OP希望返回包括历史在内的本地信息。 SSH接管了它,并且不响应CTRL-C之类的常规中断序列,因为它传递了这些序列。有一种方法可以打通并终止本地客户端,请参见我的回答。如果再次登录,通常会保留本地端的历史记录,具体取决于shell配置。

–卡莱布
2011-6-22 18:20



@Caleb:该问题专门提到了丢失历史记录,命令历史记录存储在服务器端。要告诉服务器对历史记录做不同的事情,您需要向服务器发送一条消息,告诉服务器对历史记录做不同的事情。当然,有一些方法可以使bash(和一些其他shell)立即记录历史记录行,而不是将它们收集在RAM中,直到用户通过退出/注销正确存在该shell为止,这将解决历史记录问题而无需使用屏幕。

– David Spillett
2011年6月22日19:44

#5 楼

就我而言,问题在于MTU大小过大。如果使用NAT,则可以在路由器上更改MTU,但是我可以在服务器上更改MTU:

sudo /sbin/ifconfig eth0 mtu 1036
sudo /etc/init.d/networking restart


在Windows上,您也可以增加此键:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
"TcpMaxDataRetransmissions"=dword:00000010