问题是因为expect "$*"。
如果要匹配文字的美元符号($),则在双引号内使用时应使用以下方式。
expect {\\\$}
由于$ 符号对于tcl 和expect 都是特殊的,为了匹配文字的美元符号,我们需要用反斜杠两次转义它,当然还要再用一个反斜杠来转义反斜杠本身。
还有2个可以做的增强功能如下,
要通过expect 发送“输入/返回”键,我们建议使用\r,而不是\n。 (虽然你的问题没什么大不了的。:))
在生成 ssh session 之前,您将覆盖 known_hosts 文件 (> ~/.ssh/known_hosts),因此您期望只有当主机是系统新主机时才会出现“(是/否)”。
spawn ssh "$IP" -l root
expect "(yes/no)?
在exp_continue 的帮助下,我们可以在不覆盖 known_hosts 的情况下进行处理。 (但是,如果每次删除已知主机是你的真实意图,你不需要添加这部分)
通过在您的脚本中组合这些更改,它将如下所示,
#!/bin/bash
if [ "$#" -eq 0 ]; then
IP="10.104.24.196"
else
IP="$1"
fi
PWD="something"
echo "Connecting to $IP with password:$PWD"
# I have commented this line, since I am using exp_continue.
# If you don't want, then keep your code as such
#> ~/.ssh/known_hosts
/usr/bin/expect -<< EOD
set timeout 60; # 1 min of timeout
spawn ssh "$IP" -l root
expect {
# you can keep your old code here if you want.
"(yes/no)" {send "yes\r";exp_continue}
"password"
}
send "$PWD\r"
expect {\\\$}
send "cd somewhere\r"
send "./db_deploy.sh\r"
expect "Script execution completed."
send "cd somewhere\r"
send "./apps_deploy.sh\r"
expect "Script execution completed."
send "exit\r"
expect eof
EOD
除了将expect脚本直接嵌入bash脚本之外,你可以单独保存文件并调用expect脚本如下,
expect -c yourscript.exp
查看here 以了解在将期望脚本嵌入 bash 脚本时如何使用双引号和单引号。
更新:错过timeout 值我是多么可怜。
expect 的默认超时值为 10 秒。这可以通过设置一个新值来改变。
set timeout 60; # This value is in terms of seconds.
通过将超时设置为 -1,我们让它无限等待。您已经使用了该值。尝试将其更改为其他值(例如 60,即 1 分钟)。
也许,在您的情况下,如果 $ 没有匹配到,它将照此进行。如果您想优雅地处理timeout,您应该使用以下内容。
expect {
{\\\$} {puts "matched dollar sign"}
timeout { puts "timeout happened"}
}
这仍然不能准确回答您的问题。您可以尝试使用带有-d 标志的expect 并在您的问题中分享输出吗?以便我们为您提供帮助。