屏幕或类似屏幕,用于自动恢复不稳定的ssh连接


18

我经常不得不在不可靠的wifi环境中通过ssh连接到服务器。在服务器上,我运行屏幕,因此,如果断开连接,我可以重新连接并恢复屏幕会话,并从中断的地方继续接听,但是失去连接仍然是一个主要的时间浪费:如果在我连接断开时在服务器上,终端窗口趋于冻结。我必须杀死该选项卡,打开一个新选项卡,再次SSH到服务器并恢复屏幕会话。我已经在服务器上运行屏幕并在本地屏幕上尝试过此操作。无论哪种方式,当连接断开时,它都倾向于冻结。

有什么办法可以使我拥有与屏幕类似的东西,或者屏幕本身,它们将自动尝试重新连接并保持会话运行,因此我不必保持手动重新连接?通常,当我失去连接时,我认为这只是一个很短的时间-可能不到一秒钟。

我正在使用Ubuntu 14.04 LTS MATE版。谢谢


4
关于“ shell窗口趋于冻结”:这是因为您的本地ssh不知道连接已死。点击<Enter>并输入~.以告知您的一方断开连接,您只需重复上一个ssh命令即可重新连接(例如,使用向上箭头或!!)。
Alexis

@alexis听起来像是重新连接的捷径,谢谢!我希望它能自动发生……
Max Williams

Answers:


23

您可以使用mosh以下方法查看:https : //mosh.org/

您可以使用可靠的互联网连接来设置“跳转”服务器mosh,然后使用该连接来连接到ssh所管理的每台服务器。我建议使用跳转服务器的原因是,您可能不希望mosh在要管理的服务器上安装。

它的另一个优点mosh是它基于UDP而不是TCP,并且您的会话可以承受IP地址更改的影响,例如从WiFi到移动互联网连接。

只是要说清楚,mosh不是的替代screen,而是ssh。结合使用它仍然是一个好主意screen,因为mosh如果客户端由于某种原因死亡,它本身不会提供重新连接到会话的方法。


谢谢,它只是一台服务器(大部分时间),我们拥有它,因此我应该能够安装Mosh。我会检查出来的。
Max Williams

实际上,事实证明,因为我们的服务器相当旧(或者我应该说运行的是旧版Ubuntu),所以安装起来太困难了。:(
马克斯·威廉姆斯,

@MaxWilliams多大了?甚至LTS 12.4也已不再受支持。为什么不尝试自己编译呢?
phuclv

在阅读mosh文档时,您需要在打算远程管理的每个主机上安装mosh-server。仍然,绝对有趣。
通配符'18

1
对我来说,通过mosh连接到tmux终端是最稳定的解决方案。
Nemo

3

我已经使用tmux了几年了,根据我的经验,它会自动重新连接。至少当连接仅在相对较短的时间内失败时。请注意,我实际上使用byobutmux作为后端。我不知道这是否是稳健性的特点tmux或者byobu甚至是两者的结合,但我建议你给双方一试。

我通过VPN从本地Arch安装连接到各种远程Ubuntu服务器。我刚刚通过连接到遥控器的同时拔下了网络电缆进行了测试。会话已挂起,但是一旦我的电缆再次插入,它就会无缝恢复。

但是,当我通过重启路由器进行测试时,连接未恢复。我认为这与网络宕机时间有关,但是如果只是几秒钟,它似乎确实会重新连接。

如果相关,我将所有这些terminator用作终端仿真器。

这三个都可以在Ubuntu存储库中找到:

sudo apt-get install tmux terminator byobu

但是,我不敢肯定,要么tmux或者byobu是在处理SSH连接断开更好。我只知道,根据我的经验,它们通常是由于短连接损耗而恢复的。不过,这可能与我配置的其他方面有关。


1
重新启动路由器后,可能会给您另一个公共IP地址,该地址将断开tcp连接。根据我的经验,ssh对于间歇性的网络中断,我非常有弹性,我认为这与您在窗口tmux内使用的事实无关ssh
生锈的shackleford

3
我要说的是一样的:即使使用普通的SSH,只要TCP连接不会消失,就可以处理短暂的断开连接。如果您的接口关闭了,或者某个狂热的路由器杀死了它(NAT路由器可能会在重新启动时忘记NAT状态,并破坏现有的连接),或者ClientAlive/ ServerAlive触发器,那么可能byobu会发生什么呢,或者... 。
ilkkachu

是的,但是OP似乎在任何连接失败时都处于冻结状态,而我没有。但是,是的,您是对的,我也看到了简单的ssh且没有tmux的情况。尽管如此,也许屏幕无法处理?
terdon

2
@MaxWilliams tmux基本上是的更现代替代品screen,是的。当我刚开始像现在这样工作并需要这种东西时,我粗略的阅读建议这tmux是当今最好的选择。我也不是100%确信它可以更好地管理丢失的连接,我所知道的是,从我的经验来看,它确实可以从短暂的故障中恢复过来。无论是归结为tmux还是其他原因,我都不知道。但是似乎值得尝试:)。Byobu基本上是screen / tmux的前端,而不是GUI终端模拟器。但是它非常有用:byobu.org
terdon

2
tmux对连接中断不做任何事情。它与ssh提供的终端设备一起使用。一切都因ssh连接而落下。
JonasSchäfer18年

2

使用ssh的ServerAlive选项来检测连接何时失败。

ServerAliveCountMax
设置在不通过ssh(1)接收来自服务器的任何消息的情况下可以发送的服务器活动消息的数量(请参阅下文)。如果在发送服务器活动消息时达到此阈值,则ssh将与服务器断开连接,从而终止会话。重要的是要注意,服务器活动消息的使用与TCPKeepAlive(下文)有很大不同。服务器有效消息是通过加密通道发送的,因此不会被欺骗。由TCPKeepAlive启用的TCP keepalive选项是可欺骗的。当客户端或服务器依赖于知道连接何时变为非活动状态时,服务器活动机制非常有用。

默认值为3。例如,如果ServerAliveInterval(请参见下文)设置为15,而ServerAliveCountMax保留为默认值,如果服务器无响应,则ssh将在大约45秒后断开连接。

ServerAliveInterval
设置超时间隔(以秒为单位),如果没有从服务器接收到任何数据,则ssh(1)将通过加密的通道发送消息以请求服务器的响应。默认值为0,表示这些消息将不会发送到服务器。

因此,如果您将其设置ServerAliveInterval为5,ssh则在网络瘫痪15秒钟后会自动断开连接。


要强行中断SSH会话,请按~.(或先按Enter键,然后按~.~,该命令包括:转义符和中断会话的命令.
imz-Ivan Zakharyaschev

@ imz--IvanZakharyaschev假定您可以确定连接已挂起。使用SSH的keepalive将自动检测到故障。
Barmar

听起来真的很有用,谢谢,下次我进入“片状区域”时,我一定会尝试一下。
Max Williams

@Barmar是的,是的。我还考虑过确定连接是否真正挂起的问题,或者我按某些东西可能会意外地将这些键发送到远程端...而且我不知道一个好的解决方案。
imz-伊万·扎哈拉里舍夫(Ivan Zakharyaschev)

2

在类似的情况下,我倾向于eshell在Emacs中使用TRAMP(通过ssh)。TRAMP会在必要时进行重新连接,而不会给我带来麻烦的远程外壳命令麻烦。

但是,eshell不能作为终端使用,例如,运行在终端上执行某些特殊操作的命令,或者连续(增量地)打印出某些内容并运行相当长一段时间的命令。

基本上,在Emacs中使用TRAMP开始使用它非常简单:

M-x eshell
cd /user@host:

1

免责声明

如果您的SSH连接无法在短暂的网络中断中幸存下来,则说明还有其他事情正在发生,这让sshTCP不能正常工作。

有关详情,请参见下文。无论如何:

最快最脏的无依赖性解决方案

创建如下的shell脚本:

#!/bin/sh -

# Tune these numbers depending on how aggressively
# you want your SSH session to get reconnected.
timeout_options='-o ServerAliveInterval=4 -o ServerAliveCountMax=2'

# 255 is the status OpenSSH uses to signal SSH errors, which
# means we want to connect. All other exit statuses suggest
# an intentional exit.
status=255

# Keep opening the SSH connection and immediately dropping into
# `screen` until an intentional exit happens.
while [ "$status" = 255 ]
do
    ssh $timeout_options -t "$@" screen -dR
    status=$?
    # You can add a `sleep` command here or a counter or whatever
    # you might need as far as rate/retry limiting.
done
exit "$status"

这只会运行一个愚蠢的简单循环,并不断尝试连接ssh和附加到screen。将主机或通常传递给ssh调用的其他任何内容作为命令行参数传递。

重新连接仅基于SSH是否报告连接错误,这意味着它不具有检测非SSH错误(例如“您确实没有打开WiFI”之类的信息)的智能,但对于您。

我假设您拥有ssh-agent一个或无密码的SSH密钥,该密钥将允许重新连接在您没有其他输入的情况下正常工作。

这将是一个很小的竞争条件,如果您^C在重新连接期间恰好在人类无法察觉的瞬间击中,您最终可能会杀死脚本,而不是将脚本传递^C给客户端,因此如果您怀疑连接挂起不要^C太热心捣碎。

最简单的附加软件解决方案

您可以尝试程序autossh,该程序应该在Ubuntu软件包存储库中可用。

如果您需要从源代码构建或对其进行审核,则它是一个C程序,无需任何其他库就可以进行编译作为依赖项,与上面的hack相比,它似乎在检查连接活动性方面更具智能,并且还附带了一个方便的rscreen脚本命令,该命令可以自动-附加到screen

细节

如何ssh恢复正常后

只是为了验证,因为我不喜欢自己检查自己说的话,所以我在回答之前做了一点测试:

我使用Linux设备进入WiFi,与LAN上的另一设备建立SSH连接,验证我ssh与另一端的连接正常(可以运行命令等),然后客户端断开WiFi(导致接口断开)要取消配置:没有更多的IP地址),在ssh会话中键入了一堆更多的字符(当然没有响应),然后重新连接到我的WiFi-由于信号不良和其他因素,重新连接实际上至少失败了一次,然后终于重新连接:我等待了大约五秒钟,ssh会话恢复了,什么也没发生,所以我又按下了一个键,ssh会话立即又恢复了活动,断开时我键入的所有键都出现在命令行中。

见,ssh只是写/读入TCP网络套接字,直到OS告诉它出事了,而实际上TCP是非常宽容的延长连接滴。

在默认内核设置下,将其放置在自己的设备上,Linux中的TCP堆栈将很高兴地允许连接完全静默很多分钟,然后再声明连接已死并向其报告错误ssh-直到它最终放弃时,我们正在讨论大约30分钟,或者至少肯定长到足以使连接打last持续一秒或一分钟。

然而,在幕后,Linux TCP堆栈会逐渐重试消息,并且延迟越来越长,这意味着到连接恢复时,您可能正在等待其他延迟,然后ssh会话才能再次“活跃”。

为什么有时会中断

通常,在闲置时间比TCP堆栈所允许的时间短得多的情况下,主动导致连接关闭的原因是某些原因,然后无法向ssh客户端报告该连接状态。

可能的候选人包括:

  1. 防火墙或NAT'ing路由器必须使用内存来记住每个实时TCP连接-作为对DOS攻击的一种优化和缓解措施,它们有时会忘记您的连接,然后静默忽略随之而来的数据包,因为当您不记得现有连接时,在连接的中间看起来无效。

  2. 行为良好的防火墙/路由器将注入TCP RST数据包,该数据包通常显示为connection reset by peer错误消息,但重置数据包是一劳永逸的,因此,如果此时与客户端的连接仍然有问题,则丢弃也重置数据包,您的客户端会认为连接仍然有效。

  3. 服务器本身可能具有防火墙策略,以静默方式丢弃意外的数据包,每当服务器认为连接已关闭但客户端没有关闭时,这都会破坏客户端的连接恢复尝试:您的客户端一直在尝试继续连接,但服务器只是忽略它是因为在服务器的防火墙状态下没有这些数据包所属的实时连接。

    由于您运行的是Linux,因此请仔细检查服务器的iptables/ ip6tables(或者nft您是否在使用新的东西),以准确了解允许或删除的内容。在TCP SSH端口上允许新的 /已建立的 / 相关的数据包是很常见的,但不允许 “无效”的数据包-如果您无声地丢弃所有不允许的数据包,则这种常见的设置可能会在短暂的连接问题后导致这些冻结。

  4. 您的SSH服务器本身可能被配置为在一段时间不活动之后使用TCP或SSH客户端keepalive数据包的OpenSSH选项之一关闭连接。就其本身而言,这不会导致不确定的挂起,但可以使您进入上述状态之一。

  5. 进入ssh会话挂起的状态后,您可能没有给它足够的时间自行“取消挂起”。

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.