一个有趣的bug记录--为什么不建议随便选ssh终端

症状很奇特:ghostty连接多个vps都会在#后面输出日志:flushed_face:

选ghostty这种没问题;只是有点小异常。只是看到最近流行vibe coding之后出现了不少自创的ssh客户的,不敢随便用。

AI的解释下面的是正确的。之前猜测了ssh的版本问题,还有LOGLEVEL的问题。

关闭 Ghostty 后重新打开,问题就神奇地消失了——这是一个极其关键的线索!结合你使用的 OpenSSH 9.9 版本,我们可以断定:这并不是 Ghostty 的 Bug,也不是 OpenSSH 9.9 打印日志的 Bug,而是由“幽灵进程”或“临时会话状态”引起的。

最合理的解释指向了一个 SSH 的高级特性:SSH 连接复用(ControlMaster / ControlPersist)

下面为你拆解这个“灵异事件”背后的真正原因:

嫌疑人一:SSH 连接复用(ControlMaster)导致的“日志继承”(可能性 90%)

如果你在 ~/.ssh/config 中配置了类似 ControlMaster autoControlPersist(很多开发者或自动化脚本会默认开启它以加速 SSH 登录),那么 SSH 会在后台建立一个主连接(Master Connection)。

案发还原:

  1. 第一次连接(带了调试参数): 你(或者你运行的某个部署脚本、Git 插件等后台工具)在那个 Ghostty 窗口里,曾以带有 -vvv(或极高日志级别)的方式连接过这台 VPS。
  2. 驻留后台: 因为开启了连接复用,这个带有 -vvv 属性的主 SSH 进程并没有真正退出,而是变成了一个 Socket 监听进程驻留在后台。
  3. 你的操作: 当你后来手动输入普通的 ssh vps 时,SSH 发现后台已经有一个主连接了,于是直接挂载到了那个带有 -vvv 属性的主连接上
  4. 日志泄露: 主连接在处理键盘时序模糊化(Obfuscate Keystroke Timing)时产生的 debug3 底层日志,顺着复用通道“溢出”到了你当前的终端屏幕上。尽管你当前的命令和配置都是 ERROR 级别,但主进程的级别盖过了一切
  5. 为何重启消失: 当你彻底关闭 Ghostty 时,不仅清理了 Shell,往往也切断了那个驻留后台的 SSH 主进程(或者经过这段时间,ControlPersist 的存活时间刚好超时了)。当你重新打开 Ghostty 并连接时,SSH 建立了一个干干净净的、全新的(无 -vvv 的)主连接,问题自然就消失了。

嫌疑人二:Shell 会话的“临时状态”污染(可能性 10%)

每个打开的终端窗口(Session)都是独立的。如果你在那个特定的 Ghostty 窗口里执行过以下操作,关闭窗口就会清空这些状态:

  1. 临时别名 (Alias): 你可能曾为了排查网络,随手打过一句 alias ssh='ssh -vvv'。只要这个标签页不关,之后你敲的所有 ssh 都会带上调试信息。
  2. 环境变量污染: 某些辅助工具可能临时注入了环境变量,强制拉高了 SSH 的 Verbose 级别。

有没有已知的相关 Bug?

在 OpenSSH 9.5 引入 obfuscate_keystroke_timing 之后,在 9.9 版本中并没有“在不加 -v 的情况下强行输出 debug3”的已知 Bug。

业界(包括 Github 和 StackOverflow)遇到的几乎所有“未加 -v 却看到 chaff packets sent 提示”的案例,最后排查出来的原因都是:用户忘记了自己在一个存活的连接复用(ControlMaster)进程中开启了 -vvv,或者别名中隐藏了该参数。

总结与建议

这次事件只是虚惊一场,是之前调试状态遗留的“影子”干扰了你的视线。Ghostty 没有任何问题,你可以放心继续使用。

如果你想彻底杜绝这类“幽灵日志”再次出现,只要像之前建议的那样,在 ~/.ssh/config 里加上 ObfuscateKeystrokeTiming no 即可,这不仅能屏蔽日志,还能稍微节省一点点 VPS 的网络包开销。