如何在不导出变量的情况下让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
相关产品推荐
相关产品推荐

