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,提问作者闫之明
相关产品推荐
相关产品推荐

