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

Expect脚本故障排查:登录服务器后无法运行本地脚本

问题原因分析

你遇到的问题核心在于Expect的spawn命令不会像bash那样解析重定向符号<。当你直接在bash里执行ssh ... bash -s < ./emrScript.sh时,是本地bash把< ./emrScript.sh解析为“将本地脚本内容作为标准输入传给ssh命令”,远程的bash -s会从标准输入读取脚本内容并执行。

但在你的Expect脚本里,< ./emrScript.sh被当成了ssh命令的一个参数直接传给了远程服务器。远程服务器的bash收到这个参数后,会尝试在服务器本地查找./emrScript.sh文件——而这个文件只存在于你的本地机器,所以自然会报“找不到文件”的错误。

两种修复方案

方案一:让本地shell处理重定向

把ssh命令放在本地bash的子shell里执行,这样重定向会被本地shell解析,而不是作为参数传给远程。修改你的spawn行如下:

spawn bash -c "ssh -o StrictHostKeyChecking=no $username@$sshHost 'bash -s' < ./emrScript.sh"

这样bash -c会启动一个本地bash进程,由它来处理< ./emrScript.sh的重定向,把本地脚本内容通过ssh的标准输入传给远程的bash -s,和你直接在终端执行ssh命令的逻辑完全一致。

方案二:手动读取本地脚本并发送给远程

如果你不想依赖本地bash,可以在Expect里先读取本地脚本的内容,然后把内容发送给远程的bash -s。修改后的脚本如下:

#!/usr/bin/expect
set username [lindex $argv 0]
set password [lindex $argv 1]
set sshHost [lindex $argv 2]

# 读取本地脚本内容
set script_file "./emrScript.sh"
set fh [open $script_file r]
set script_content [read $fh]
close $fh

# 启动ssh连接,只执行bash -s(等待输入脚本内容)
spawn ssh -o StrictHostKeyChecking=no $username@$sshHost "bash -s"

# 处理密码提示,发送密码后再发送脚本内容
expect "Enter your AD Password:" {
    send "$password\r"
    send "$script_content\r"
    expect eof
}

# 捕获退出码并返回
catch wait result
exit [lindex $result 3]

这个方案的逻辑是:先连接远程服务器启动bash -s(它会等待标准输入的脚本内容),输入密码后,把本地脚本的内容全部发送给远程bash,让它执行。

额外小提示

你原来的Expect代码里,expect eof直接写在send后面的同一行,虽然语法没问题,但拆分到多行可读性更好,就像方案二里的写法一样。

内容的提问来源于stack exchange,提问作者KBouldin9

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:33:55