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

如何在不导出变量的情况下让Expect脚本读取Shell变量?

解决Expect不读取未导出Shell变量的问题

问题核心是你使用了带单引号的Here文档(<<'END_EXPECT'),Shell会完全跳过对文档内变量的替换,导致Expect将$D视为自身未定义的变量,从而报错。以下是几种无需导出变量的解决方法:

方法一:移除Here文档的单引号,让Shell提前替换变量

将<<'END_EXPECT'改为<<END_EXPECT,Shell会先把文档内的$D替换为实际值,再传递给Expect。如果Expect脚本内有自身的$开头变量(比如$timeout),若Shell中不存在同名变量则无需处理,否则可以给Expect变量前加反斜杠转义(\$timeout)。

修改后的完整脚本:

D=`s="$LIST1" printenv s |grep $ip | awk '{print $3}'`

/usr/bin/expect <<END_EXPECT
set timeout -1
log_file  expect-log.txt
spawn -noecho sh ./script.sh
expect "yes" { send "yes\r"}
expect {
    -nocase "*assword*" {
        send "$D\r"
        exp_continue
    }
    eof
}
END_EXPECT

注:修正了你原Expect脚本中send和eof的语法错误,确保逻辑正确。

方法二:通过Expect命令行参数传递变量

使用expect -c参数在启动时直接定义Expect变量,同时保留Here文档的单引号(避免Shell误替换其他内容)。如果密码包含特殊字符(空格、引号等),用printf处理转义更安全。

示例:

D=`s="$LIST1" printenv s |grep $ip | awk '{print $3}'`

/usr/bin/expect -c "$(printf 'set D {%q}' "$D")" <<'END_EXPECT'
set timeout -1
log_file  expect-log.txt
spawn -noecho sh ./script.sh
expect "yes" { send "yes\r"}
expect {
    -nocase "*assword*" {
        send "$D\r"
        exp_continue
    }
    eof
}
END_EXPECT

方法三:通过临时文件传递变量(不推荐,仅作补充)

将变量写入临时文件,让Expect读取后删除,适合对命令行参数敏感的场景:

D=`s="$LIST1" printenv s |grep $ip | awk '{print $3}'`

tmpfile=$(mktemp)
echo "$D" > "$tmpfile"

/usr/bin/expect <<'END_EXPECT'
set timeout -1
log_file  expect-log.txt
spawn -noecho sh ./script.sh
expect "yes" { send "yes\r"}

# 读取临时文件中的密码
set tmpfile [lindex $argv 0]
set fd [open "$tmpfile" r]
set D [read $fd]
close $fd
file delete "$tmpfile"

expect {
    -nocase "*assword*" {
        send "$D\r"
        exp_continue
    }
    eof
}
END_EXPECT "$tmpfile"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:54:28