首页 > 解决方案 > 如何在期望脚本中处理来自 passwd 的错误?

问题描述

我正在尝试创建一个期望脚本来以非交互方式更新用户的密码。新的期望和 shell 脚本。我希望能够捕获和处理遇到的错误。例如,如果我正常运行 passwd,并且由于某种原因我的新密码不可接受,我可能会看到一条消息,如“密码错误:密码与旧密码太相似”。问题是,在期望脚本中,在使用无效密码发送 $new_pswd\r 后,期望“BAD PASSWORD:*”失败,因为 passwd 的下一个输出是“”。我想捕获错误的密码和消息,以便我可以将它们返回给调用进程。这里的用例是允许可能拥有多个帐户的个人用户一次性使用相同的密码更新他们的所有帐户。

#!/usr/bin/expect -df

# THIS SCRIPT WON'T WORK
set old_pswd $::env(PSWD1)
set new_pswd $::env(PSWD2)

spawn passwd
expect "*ssword:" { send "$old_pswd\r" }
expect "*ssword:" { send "$new_pswd\r" }
expect {
        "*ssword:" {
                puts "Expected\r"
                send "$new_pswd\r"
                exit 0
        }
        "BAD PASSWORD:*" {
                puts "BAD PASSWORD\r"
                send \x03
                exit 1
        }
        "*" {
                puts "Unexpected\r"
                send \x03
                puts $expect_out(buffer)
                exit 1
                }
        }

标签: expectpasswd

解决方案


更新:从昨天开始,我学到了很多关于 expect 的知识,最终解决了这个问题和脚本中的其他几个问题。

第一个问题是我希望密码提示在冒号后没有空格,因此所有后续的期望命令都试图匹配尚未使用的空格字符,该字符与“*”匹配,并在 passwd 之前终止脚本曾经发送过错误的密码消息。

第二个问题是试图匹配 *ssword: 在“BAD PASSWORD”之前。新密码提示总是在 BAD PASSWORD 消息之前匹配,因为 passwd 正在发送“BAD PASSWORD: message message message\r\nNew password:”

这是一个现在可以工作的脚本,它被包裹在一个 su 中。调用此脚本的任何进程都需要在之后清理环境变量。这个想法是提前安全地设置这些,这样就不必在命令行上传递凭据。此脚本旨在为属于他们的每个其他帐户从用户帐户调用一次:

#!/usr/bin/expect -f

# THIS SCRIPT WORKS
set old_pswd $::env(PSWD1)
set new_pswd $::env(PSWD2)
set new_user $::env(USER1)

spawn su $new_user
expect "*ssword: " { send "$old_pswd\r" }

expect "$ " { send "passwd\r" }
expect "*ssword: " { send "$old_pswd\r" }
expect "*ssword: " { send "$new_pswd\r" }

expect {
        "BAD PASSWORD: " {
                expect {
                        "dictionary"    { set exit_code 1 }
                        "shorter than"  { set exit_code 2 }
                        "too similar"   { set exit_code 3 }
                        "No password"   { set exit_code 4 }
                        "*"             { set exit_code 99 }
                }
                send \x03
                expect "$ " { send "exit\r" }
                exit $exit_code
        }
        "*ssword: " {
                send "$new_pswd\r"
                expect "$ " { send "exit\r" }
                exit 0
        }
}

推荐阅读