将参数传递给 shell 脚本时期望 shell 的不稳定行为



这段代码在没有命令行参数的情况下工作正常,但是当我将IP作为参数传递给脚本时,登录linux框后停止

bash -x -o igncr Master.sh 10.104.24.196

我不知道发生了什么,任何帮助将不胜感激。

if [ "$#" -eq 0  ]; then
IP="10.104.24.196"
else
IP="$1"
fi
PWD="something"
echo "Connecting to $IP with password:$PWD"
> ~/.ssh/known_hosts
/usr/bin/expect -<< EOD
set timeout -1
spawn ssh "$IP" -l root
expect "(yes/no)?"
send "yesn"
expect "password"
    send "$PWDn" 
    expect "$*" <- stops here
    send  "cd somewheren"
    send "./db_deploy.shn"
    expect "Script execution completed."
        send "cd somewheren"
        send "./apps_deploy.shn"
        expect "Script execution completed."
            send "exitn"
expect eof
EOD
#dosomething else

问题是因为expect "$*" .

如果要

匹配文字美元符号 ( $ (,那么在双引号内使用时应使用以下方式。

expect {\$}

由于$符号对tclexpect都是特殊的,为了匹配字面上的美元符号,我们需要用反斜杠转义它两次,当然还需要一个反斜杠来转义反斜杠本身。

还有 2 个可以完成的增强功能如下:

要通过expect发送"输入/返回"密钥,建议使用r,而不是n。 (虽然在你的问题中没什么大不了的。 :)(

在生成 ssh 会话之前,您正在覆盖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 "yesr";exp_continue}
        "password" 
}
send "$PWDr" 
expect {\$}
send  "cd somewherer"
send "./db_deploy.shr"
expect "Script execution completed."
send "cd somewherer"
send "./apps_deploy.shr"
expect "Script execution completed."
send "exitr"
expect eof
EOD

与其将期望脚本直接嵌入到 bash 脚本中,不如单独保留文件并调用 expect 脚本,如下所示,

expect -c yourscript.exp

查看此处以了解在 bash 脚本中嵌入 expect 脚本时双引号和单引号的用法。

更新:我错过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并在您的问题中分享输出吗?以便我们为您提供帮助。

最新更新