那阵子在给七亿批量远程管理工具里那个 SSH 运维助手补「逐步执行」——AI 每次只吐一条命令,客户端拿去在服务器上跑,再把真实回显喂回去,跟 FinalShell 那种“边看结果边走”一个路子。一天从 V95 改到 V113,十八个版本,基本是冒一个坑补一个。
回头看,那两天冒出来的坑里有两类特别像:都是“命令发出去,那头一点反应没有”,但根子完全两回事。
先说 heredoc。
助手给的命令,写配置文件那种,经常是一整段:
cat > /etc/3proxy.cfg <<'EOF'
...
EOF我原以为整块发下去就完事。结果服务器上文件根本没生成,if [ ... ]; then ... fi 这种多行判断也一样,直接报语法错。第一反应是 AI 生成的命令本身有毛病,把它单独抄出来手敲,一模一样,跑得通。
那问题就在客户端这头。去翻发命令那段代码——它是按行切的:一个 `sh 代码块里,每一行当一条命令依次发出去。于是 cat > ... <<'EOF' 单独发一条,中间那些配置内容每行发一条,末尾的 EOF 再单发一条;if 和 fi 也被拆到了两条里。落地的就是几条互不相干的东西。
改起来其实一句话:一个 sh 代码块 = 一条命令,整块原样发下去。多行、heredoc、行尾续行,都交给 SSH 那头一次跑完。改完 heredoc 就正常了。
这个坑让我嘀咕了好一阵——命令本身“看着”没毛病,锅在传输那一层。那天这台机器本来就是拿来装 3proxy 的,用户等着一个能用的 SOCKS5,结果卡在几条静默发出去的命令上,界面那边看着就像助手罢工了。
第二个更阴。
有次让它停一个进程,它给了 pkill -f '/usr/bin/3proxy'。发出去,整段没有任何输出,光标也不回来,像网断了。我先怀疑是命令太长、服务器卡了,重连、重开窗口,折腾几分钟。
后来把这条命令自己在终端里敲了一遍——终端直接退出了。
才反应过来:pkill -f 是拿整条命令行去匹配的。而执行这条 pkill 的那个 shell,命令行里就带着 /usr/bin/3proxy 这串字,等于把它自己也匹配上了,顺手发了个 SIGTERM。命令把自己杀了,自然就没有下文。
这个坑在“让 AI 生成命令”的场景里尤其值得记,因为它不是偶发:你要杀哪个进程,命令行里就写着哪个名字。后来给了两条处理法:要么 pkill -x 进程名,只匹配进程名、不看整条命令行;要么给模式加个中括号,pkill -f '[3]proxy'——命令行里剩下的是 [3]proxy,匹配不上 3proxy 本身。ps | grep 同理,写成 [x]xx。
我把这条当成“生成命令时的常识”塞进了提示词,省得它下次再想出自杀写法。这跟给助手对话历史塞上限那篇是一上一下两件事:那篇管的是往上怎么喂上下文,这两条管的是往下命令怎么落地。合起来才勉强算把“发一条命令”这件事做圆。
SSH 终端本身该怎么用,教程页上写得比我清楚,我这边都是被坑教会的。
评论