You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js调用Expect脚本时while循环内Expect失效问题

问题分析与解决方案

你的核心问题是:通过Node.js调用Expect脚本时,while循环内的expect语句无法匹配到ssh-copy-id的交互提示符,但直接运行脚本一切正常。这大概率是因为Node.js执行脚本时,没有为Expect及其子进程分配交互式终端环境,导致ssh-copy-id不输出预期的提示信息。

以下是针对性的解决方案:


方案1:设置TERM环境变量

ssh-copy-id等交互式工具依赖TERM环境变量判断是否处于终端环境。在Node.js执行脚本时显式设置该变量:

app.post("/sparknode/ssh/setssh", cors(), (req, res) => {
    shell.exec("TERM=xterm expect /root/suanchang/set-ssh.sh", { async: false });
    res.send("success");
});

方案2:直接Spawn ssh-copy-id进程

去掉Expect脚本中bash -c的包装层,直接启动ssh-copy-id,减少不必要的shell层级干扰:

# 替换原while循环内的spawn语句
# spawn bash -c "ssh-copy-id -f $username@$ip"
spawn ssh-copy-id -f "$username@$ip"

方案3:使用Node.js原生Spawn分配伪终端

放弃shell.exec,改用Node.js原生child_process.spawn并配置终端继承,确保Expect进程获得完整的终端环境:

const { spawn } = require('child_process');

app.post("/sparknode/ssh/setssh", cors(), (req, res) => {
    const child = spawn('expect', ['/root/suanchang/set-ssh.sh'], {
        stdio: 'inherit', // 继承当前终端的输入输出
        shell: true
    });

    child.on('close', (code) => {
        res.send(code === 0 ? "success" : "failed");
    });
});

调试验证步骤

在Expect脚本开头添加exp_internal 1,开启Expect的调试模式。通过Node.js执行脚本后,查看输出日志,确认ssh-copy-id是否输出了预期的"are you sure..."或密码提示符,以此验证问题根源。


内容的提问来源于stack exchange,提问作者闫之明

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:47:06