2

我制作了一个 Bash 脚本,它使用一个期望脚本来自动化 ssh 登录。该脚本连接到多个服务器并运行一些命令。bash 脚本会提示输入登录凭据一次。

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

这是 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 命令输出$?(任何建议将不胜感激。

4

5 回答 5

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 文件的内容。如果您确实关心,则需要获取外壳告诉你:

send -- "opcagt -status 2>&1 || echo "non-zero return from opcagt: $?"
expect {
    "non-zero return" { handle error and exit? }
    -re $prompt
}
# ... continue
于 2009-08-20T13:21:12.647 回答
1

这部分:

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

在我看来非常可疑。特别是,我真的希望这会导致事情变得混乱。一种更惯用的写作方式是:

    expect  {
        "assword:" {
            send "$SPASS\r"
            exp_continue
        }
        -re "$prompt"
    }
于 2010-10-02T20:12:08.580 回答
1

你应该认真看看Fabric

于 2009-08-19T19:36:46.730 回答
0

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

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

退出状态是 0 表示 true 和 1 或任何其他表示 false 的状态

您可以通过执行命令然后通过键入“echo $?”检查其退出状态来看到这一点。

我的建议是当您尝试 ssh 进入一台服务器并且身份验证失败时,应该有一个不是 0 的退出状态

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

于 2009-08-20T07:55:47.930 回答
0

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

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

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

于 2010-07-21T14:57:11.330 回答