SSH连接AWS实例执行大输出命令时终端冻结问题排查
故障背景
- 本地环境:Mac设备运行iTerm2 + Oh My Zsh终端,此前所有功能正常,故障自昨日突发
- 正常表现:SSH连接任意AWS实例时,小输出量命令(如
uptime、vmstat 1 300 -w这类逐行低速率输出命令)运行无异常;本地机器、OpenStack平台开发虚拟机SSH连接无同类问题 - 异常表现:执行
ps -ef、history、htop,或用cat查看数百行以上文件时,终端仅输出部分内容即冻结,按ctrl+c无响应,只能通过~.快捷键强制终止SSH会话后重连 - 补充测试结果:
- 大输出命令通过管道传给
less分页(如ps -ef | less)可正常运行 - 双终端同时登录同一AWS实例,分别获取pts/0、pts/1两个伪终端,在pts/0执行
echo Hello > /dev/pts/1时pts/1可正常收到消息;执行ps -ef > /dev/pts/1时,pts/1仅输出少量内容即冻结
- 大输出命令通过管道传给
- 初步排查结论:已排除iTerm2本身故障,疑似伪终端无法处理大字符流,未定位根因
根因定位与排查方案
从给出的测试现象看,90%以上概率是SSH链路PMTU(路径MTU)黑洞导致的,和pts伪终端、iTerm2、Zsh本身没有直接关系,所有现象完全匹配该故障特征:小流量、低速率发包正常,连续大流量输出时TCP连接因大包被丢弃僵死,ctrl+c无法传递到远端。
第一步:快速验证
在Mac本地终端执行如下命令连接AWS实例,强制SSH连接使用适配过的报文大小:
ssh -o IPQoS=reliability -o MSS=1360 你的AWS实例登录地址
登录后直接执行ps -ef、cat 大文件测试,如果不再出现冻结,即可确认是MTU问题。
为什么
ps -ef | less、逐行输出的vmstat能正常运行?这类场景下输出存在流控,发包速率低、单包尺寸小,不会触发中间链路丢大包的逻辑;直接全量输出大内容时,TCP会快速填充发送窗口,连续发出符合远端MTU的大包,被中间设备丢弃后又收不到ICMP分片通知,连接直接进入僵死状态,所以ctrl+c的中断信号也传不到远端。
第二步:修复方案
临时生效方案
直接修改Mac本地的SSH客户端配置,全局强制SSH连接使用合理的报文参数,编辑~/.ssh/config,添加如下配置:
Host * IPQoS reliability MSS 1360
保存后重新发起SSH连接即可生效,不需要重启任何服务。
根因修复方案
- 检查AWS侧VPC的网络ACL、实例绑定的安全组规则,确认放行了ICMP Type 3 Code 4(分片需要但DF位置位)报文,AWS EC2默认网卡开启巨帧支持,MTU为9001,如果中间链路阻挡了PMTU协商需要的ICMP报文,就会形成PMTU黑洞
- 检查本地网络出口设备(家用路由器、VPN/代理网关)的MTU配置,大部分家用宽带、企业VPN的实际MTU在1400-1492之间,和AWS侧9001的巨帧配置不匹配,且没有正确做PMTU协商时就会触发该问题
- 如果你近期调整过Mac端的网络配置、升级过系统,可临时关闭系统自带的TCP分段卸载相关功能做对照测试,这类系统级网络参数变动也可能导致PMTU协商异常。
低概率问题排查
如果上述方案验证无效,再依次排查以下场景:
- 临时切换本地Shell为bash,禁用Oh My Zsh所有自定义插件、主题后测试,排除特殊终端控制字符转义兼容问题
- 检查AWS实例侧的
/etc/security/limits.d/下的配置,确认没有误修改伪终端的缓冲区、文件句柄限制 - 用Mac自带的终端(Terminal.app)替代iTerm2做对照测试,排除终端软件的流控配置异常
内容的提问来源于stack exchange,提问作者Nagri
相关产品推荐
相关产品推荐

