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

发布于 2024-08-02 12:20:24 字数 1413 浏览 8 评论 0原文

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

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

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

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 命令输出($?),假设 bash 命令在登录时将返回非零值由于期望脚本中的密码不正确而失败,但没有成功。 任何建议将不胜感激。

I made a Bash script which uses an expect script to automate ssh logins.The script connects to multiple servers and runs some commands.
The bash script prompts for login credentials once.

I want to incorporate a feature wherein the script terminates if the login fails for the first server to avoid the script checking for next servers resulting in the user account getting locked. The account lockout happens for 3 consecutive login failures and the number of server the script tries to connect is more than 3.

This is the snippet in the bash script which calls the expect script.

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

and here is the expect script (script.expect) snippet

#!/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
    }

I tried grabbing the bash command output ($?) assuming that the bash command would return a non zero value if login fails for incorrect password in the expect script but that did not work out.
Any suggestions would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

逆夏时光 2024-08-09 12:20:24

对于期望脚本中的错误检查,有一个不错的示例 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

For error checking in an expect script, there's a decent example at http://systeminetwork.com/article/handle-errors-expect-scripts

What you should do is something like this:

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
    }
}

I assume you don't need to know about the exit status of the "opcagt ..." series of commands (you just want to see the contents of the watch.cf file. If you do care, you'll need to get the shell to tell you:

send -- "opcagt -status 2>&1 || echo "non-zero return from opcagt: $?"
expect {
    "non-zero return" { handle error and exit? }
    -re $prompt
}
# ... continue
那小子欠揍 2024-08-09 12:20:24

您应该认真看看 Fabric

You should seriously take a look at Fabric.

屋顶上的小猫咪 2024-08-09 12:20:24

该部分:

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

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

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

The section:

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

Looks highly suspicious to me. In particular, I really would expect that to cause things to become confused. A more idiomatic way of writing that would be:

    expect  {
        "assword:" {
            send "$SPASS\r"
            exp_continue
        }
        -re "$prompt"
    }
浮生未歇 2024-08-09 12:20:24

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

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

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

You're running the expect scripts in the background (&), so you can't have the results of the first one before continuing.

The way your expect script is written, it'll get a 30 second timeout at the second password prompt if the first password fails. Instead, you could do an expect alternative, to see if you get another assword prompt, and exit immediately.

Then change the shell script to not put the expect calls in the background, instead capture the output with $? and test it.

国际总奸 2024-08-09 12:20:24

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

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

东西退出状态是 0 的状态为 true,1 或其他任何值为 false

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

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

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

I am not much into scripting and all, thus I cannot write the exact steps or script to prove what I got in mind - kindly excuse

Well, I read that bash provides for a thing called as exit status

An exit status is a status of 0 for true and 1 or anything else for false

You can see this by executing a command and then checking its exit status by typing "echo $?"

What I suggest is when you try to ssh into one server and authentication fails, there shall be an exit status of something other than 0

Getting an if-then-else loop here and checking the status for 0 for execution of script and any other value to exit the script totally with a suitable error message

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文