退出从Bash调用的Expect脚本的状态代码

时间:2009-08-19 19:22:27

标签: bash login ssh tcl expect

我创建了一个Bash脚本,该脚本使用expect脚本自动执行ssh登录。该脚本连接到多个服务器并运行一些命令。 bash脚本会提示输入一次登录凭据。

我想要合并一个功能,如果第一台服务器登录失败,脚本会终止,以避免脚本检查下一台服务器导致用户帐户被锁定。帐户锁定连续3次登录失败,脚本尝试连接的服务器数量超过3。

这是调用expect脚本的bash脚本中的代码段。

countu=0
for servername in $(cat $linux_host_list)
do
./script.expect $LUSERNAME $LPASS $servername Linux >> linux_log_file.txt & < /dev/null
let countl=countl+1
done

这是期望脚本(script.expect)代码段

#!/usr/bin/expect -f
set timeout 30
set username [lindex $argv 0]
set SPASS [lindex $argv 1]
set servername [lindex $argv 2]
set case [lindex $argv 3]
set prompt "(%|#|\\$|%\]) $"
switch $case {
    Linux {
        log_user 0
        spawn ssh -o StrictHostKeyChecking=no $username@$servername
        expect  {
            "assword:" {
                send "$SPASS\r"
                expect -re "$prompt"
            }
            expect -re "$prompt"
        }
        send "sudo su -\r"
        expect {
            "assword:" { send "$SPASS\r" }
        }
        expect -re "$prompt"
        log_user 1
        send "opcagt -status ; opctemplate -l ; cat watch.cf 2> /dev/null\r"
        expect -re "$prompt"
        log_user 0
        send "exit\r"
        expect -re "$prompt"
        log_user 1
    }

我尝试抓取bash命令输出($?),假设如果在expect脚本中登录失败,但是没有用,则bash命令将返回非零值。 任何建议都会非常感激。

5 个答案:

答案 0 :(得分:2)

对于期望脚本中的错误检查,http://systeminetwork.com/article/handle-errors-expect-scripts

有一个不错的例子

你应该做的是这样的事情:

proc do_exit {msg} {
    puts stderr $msg
    exit 1
}

switch -exact -- $case {
    Linux {
        spawn ssh ...
        expect {
            -re {assword: $} {
                send -- "$SPASS\r"
                exp_continue 
                # remain in this expect block and look for the next matching pattern
            }
            "some message about incorrect password" {
                do_exit "incorrect password"
            }
            timeout {do_exit "timed out waiting for prompt"}
            default {do_exit "something else happened"}
            -re $prompt
        }
        # ... rest of your script
    }
}

我假设您不需要了解“opcagt ...”系列命令的退出状态(您只想查看watch.cf文件的内容。如果您关心,您将会需要让shell告诉你:

send -- "opcagt -status 2>&1 || echo "non-zero return from opcagt: $?"
expect {
    "non-zero return" { handle error and exit? }
    -re $prompt
}
# ... continue

答案 1 :(得分:1)

你应该认真看看Fabric

答案 2 :(得分:1)

部分:

    expect  {
        "assword:" {
            send "$SPASS\r"
            expect -re "$prompt"
        }
        expect -re "$prompt"
    }

对我来说非常可疑。特别是,我真的希望这会让事情变得混乱。更惯用的写作方式是:

    expect  {
        "assword:" {
            send "$SPASS\r"
            exp_continue
        }
        -re "$prompt"
    }

答案 3 :(得分:0)

我对脚本编写并不多,因此我无法编写确切的步骤或脚本来证明我的想法 - 请原谅

好吧,我读到bash提供了一个称为退出状态的东西

对于true,退出状态为0,对于false

,退出状态为1或其他任何状态

您可以通过执行命令然后键入“echo $?”

来检查其退出状态

我建议当你尝试ssh到一个服务器并且身份验证失败时,应该有一个非0的退出状态

在此处获取if-then-else循环并检查状态为0以执行脚本和任何其他值以完全退出脚本并显示相应的错误消息

答案 4 :(得分:0)

您正在后台运行期望脚本(&),因此在继续之前您无法获得第一个结果。

编写期望脚本的方式,如果第一个密码失败,它将在第二个密码提示时获得30秒超时。相反,您可以执行expect替代,以查看是否收到另一个assword提示,然后立即退出。

然后更改shell脚本,不将期望调用放在后台,而是使用$?捕获输出并进行测试。