侠客软件 Xiake Labs

Claude Code 通过 SSH 执行命令卡住或超时的原因与解决方法

· Claude Code · SSH · 故障排查

让 Claude Code、Codex 这类 agent 直接运行 ssh host 'command',简单任务没问题,一旦稍微复杂,就会遇到“命令卡住、两分钟后超时、agent 不知道发生了什么”的情况。原因通常是下面几类。

原因一:命令在等待交互输入

apt-get upgrade 的 [Y/n]、sudo 的密码、首次连接的主机指纹确认、git 要用户名……这些提示都会让命令停住等待输入,而 agent 的工具调用不会替它回答。

OpenSSH 下的缓解: 尽量使用非交互参数(apt-get -y、DEBIAN_FRONTEND=noninteractive)、配置密钥登录、提前把主机加入 known_hosts。但总有覆盖不到的提示。

xssh 的做法: 识别提示并报告类型,例如:

$ xssh session run w -- 'sudo apt-get upgrade'
Do you want to continue? [Y/n]
[xssh w waiting prompt=confirm]
$ xssh session send w y --enter
[xssh w done exit=0]

agent 看到 waiting prompt=confirm 就知道该回答什么;sudo 密码则从钥匙串自动代填。

原因二:任务时间超过工具调用超时

编译、迁移、备份可能运行十几分钟,而 agent 的单次工具调用通常有超时上限。超时后 ssh 连接被断开,远程命令可能随之被终止,agent 也无从得知结果。

OpenSSH 下的缓解: 用 nohup、tmux、screen 把任务放到后台,再轮询日志。需要 agent 自己管理 PID 和日志文件。

xssh 的做法: job start 在远端用 setsid + nohup 运行任务,job wait --timeout 90s 分段等待,job logs 增量读取;还会记录进程启动时间,PID 被复用时不会误杀。

原因三:每次调用都是新 shell

agent 第一次调用 cd /srv/app,第二次运行 npm test——但第二次是新连接,又回到了家目录。激活的 Python 虚拟环境、导出的环境变量也一样会丢。

xssh 的做法: 命名会话(session open)由本机守护进程持有,多次调用之间保留 cwd、环境变量和运行中的程序;加 --persist 后会话托管在远端 tmux,断网也能恢复。

原因四:超时后不知道命令有没有执行

最危险的情况:命令已经发出,但在返回结果前工具调用超时了。agent 重试一次,可能把部署、数据库迁移执行了两遍。

xssh 的做法: exec --no-wait --id deploy-123 先登记任务 ID 再发送命令。之后无论超时多少次,用同一个 ID 查询只会取回已有结果,不会重复执行。

原因五:输出太多

journalctl 或构建日志一次输出几万行,塞满 agent 的上下文,后续推理质量明显下降。

xssh 的做法: 只返回有界的首尾预览,完整输出脱敏后保存到文件,并明确报告保存和丢失的字节数,需要时再按偏移量读取。

总结

症状 根因 xssh 对应能力
卡在 [Y/n] 或密码 交互提示 提示识别 + 钥匙串代填
长任务超时中断 工具调用超时 job start / wait / logs
cd 后又回到家目录 每次新 shell 命名会话 session
重试导致重复执行 结果未知 可恢复任务 ID
上下文被日志塞满 输出无上限 有界预览 + 完整落盘

这些问题正是我们开发 xssh 的原因。它免费开源,下载 后按 快速开始 配置即可。