三种办法彻底解决SSH的 Write failed: Broken pipe 问题

文章目录

  • 问题描述
  • 原理
  • 解决方法
    • 方法1:通过客户端配置
    • 方法二:服务器端配置
    • 方法三:临时SSH命令配置
  • 总结
  • 参考文献

问题描述

在使用SSH连接远程服务器的时候,如果长时间不操作,再次进入 Terminal 时就会有卡死一段时间没有响应。等待一段时间以后,会发现以下错误提示:
Write failed: Broken pipe
同时SSH连接已经断开。有时候还会出现界面卡死没有响应的情况。最终只能重新打开终端进行连接。

原理

为了保证服务器的资源不被浪费,系统会对SSH的连接定期进行自动回收(即自动断开),其回收原则为:一个连接在规定的限制时间内没有数据传输就认定为超时,然后就会主动断开连接。 基于这个原则,如果想要保持连接,只需要在超时前发送一个空数据包即可。

解决方法

从安全和资源利用的角度考虑,长时间的连接都是不合适的,尤其是一些长期连接还没有操作的。所以为了解决这个问题,服务器在指定时间会进行判断连接状态,然后判断是否判断连接。了解了这个原理,我们可以以下三个方案来解决问题。

方法1:通过客户端配置

在客户端的 ~/.ssh/ config文件(如不存在请自行创建)中添加下面内容:
ServerAliveInterval 60
ServerAliveInterval: 客户端上设置的发送空消息至服务器的秒数以保持连接。这条语法的作用是每60秒向服务器发一个空消息。我们还可以把这个配置专门为某服务器指定,写到SSH的配置中:

Host myhostshortcut
     HostName xxx.xxx.xxx.xxx
     User root
     ServerAliveInterval 60
     ServerAliveCountMax 10

方法二:服务器端配置

在服务器的 /etc/ssh/sshd_config 中添加如下的配置:

ClientAliveInterval 60
ServerAliveCountMax 10

ClientAliveInterval: 服务器上设置的发送空消息至服务器的秒数以保持连接。上边的配置里我还开启了 ServerAliveCountMax 10,它的作用是60秒钟发送一次心跳,如果连续10次都没有响应,服务器端就断开连接。
默认值是3。

方法三:临时SSH命令配置

如果只是临时性的连接(即只作用于当前SSH),可以直接使用 ssh 命令参数进行配置。
$ ssh -o ServerAliveInterval=60 user@sshserver

总结

方法一和方法三是客户端主动发消息,而方法二是服务器端主动发消息。这两方法各有利弊,简单说一下区别。

对于客户端在线状态相对自由,可以随时上线和下线。这样的话,如果下线了,那么就无法继续发送消息,这样即使设置了 ServerAliveInterval=60,消息因掉线而无法发出。所以超时后,仍然会掉线。

对于服务器端,在设置了防掉线后,如果客户端掉线了,会根据 ClientAliveCountMax 进行反复测试,如果超过测试次数,仍然也会掉线。所以总体上可靠性比客户端的方式更好。不过需要注意的事,当服务器的连接数量较多时会产生一定的资源浪费。

参考文献

[1] What options ServerAliveInterval and ClientAliveInterval in sshd_config exactly do?.

你可能感兴趣的:(Linux)