我使用 SSH 隧道通过堡垒主机连接到一些生产 Ubuntu 系统。最近,我发现在生产系统上执行长时间运行的命令(例如备份和恢复任务或归档作业)时,我的 SSH 连接会在几分钟后断开。另一方面,如果我将堡垒和生产主机的终端会话保持空闲状态,这些连接将保持更长时间。

查看我在运行长时间任务的主机上的终端输出,它似乎从未完成过所讨论的任务,尽管到目前为止,幸运的是我还没有注意到它实际上没有完成的任何情况(这是在我不使用任何特殊措施的情况下,例如nohup)。

我不知道断线的具体时间,因为我坐的时间不够长,没看到它。当连接断开时,它来自生产主机和堡垒主机,因此推测是后者造成的。

我不确定是什么变化导致了这种行为的发生。有没有关于如何/在哪里诊断和解决这个问题的指示?


最佳答案
2

您可以使用 wireshark 监控连接,但除非您在多个位置窃听连接,否则这不一定能确定问题出现的位置。

我建议使用 ssh 的 ServerAliveInterval 来保持连接处于活动状态(并处于中间设备的状态表中),然后再尝试进一步诊断。如何做到这一点取决于您使用的客户端。如果是 openssh,则可以在命令行或 ssh_config 中设置。请参阅手册页以了解 sepcifics。

当(在哪个点)它中断时,您可以从服务器日志中推断出来。 ssh 应该会丢弃一条线,表明某个客户端已断开连接。 除此之外,开始监控网络,只有一种方法。 流量捕获可能也有帮助,但大多数情况下,它对于这项任务来说太繁重了。 如果这是几个小时的问题,您是否希望存储数小时的流量捕获?

我对这种情况发生的原因有一个解释。这完全基于这样一个事实:当您有一个空闲的 SSH 会话时,它实际上什么也不会发送。

例如,我重启了建立连接的 DSL 调制解调器;调制解调器恢复后,它继续工作,好像什么都没发生一样,因为该连接的任一端都没有遇到 TCP RST 或丢失的 ACK 或其他问题。但是,这只有在调制解调器未准备好时我不触碰会话的情况下才有效。但是,如果我在调制解调器重启时尝试对连接进行任何操作,则由于 TCP 超时,连接必然会中断。

因此,如果您使用的物理连接出现间歇性问题,则如果出现问题时未使用空闲连接,则可能不会引起注意,但如果您长时间运行的任务不断输出某些内容(甚至不会推进屏幕输出的特殊字符仍在通过网络发送),这会导致 SSH 连接在出现问题时中断。

@symcbean 在另一个答案中提出的调整建议ServerAliveInterval可能是一把双头剑。它改变了这种行为,因为空闲的客户端开始向服务器发送定期的“ping”,因此它不再是空闲的,并且它开始注意到即使是短暂的问题。甚至之前没有断开的“空闲”连接也可能会开始断开。

还要注意,这ServerAliveInterval只是单方面的。它只让客户端监控连接。可能会发生客户端由于此设置而注意到断开连接的情况,但服务器却没有注意到,因为它不在乎。服务器有一个相应的设置,ClientAliveInterval即,设置在sshd_config并使服务器以相同的方式监控客户端可用性。如果您希望双方都知道,请使用这两个功能。


值得注意的是,“像nohup这样的特殊措施”根本不是特殊措施,它们是一种很好的做法。建议在会话内运行所有长时间运行的命令,screen这些tmux命令是 nohup 的现代替代品。值得注意的例子是 Debian 系统升级手册,它建议如果您要远程执行升级,请在屏幕会话中工作。

唯一无法帮助您的情况是长时间运行的任务本身通过断开的连接传输某些内容。