【问题标题】:Error On Expect ScriptExpect 脚本错误
【发布时间】:2016-03-07 04:43:22
【问题描述】:

发送新密码后,我不断收到错误消息。它将更改密码,但不会执行脚本的其余部分。任何想法为什么它总是出错。我为不同的设备编写了一个非常相似的脚本,它运行良好,但是在该设备上不需要更改密码后的东西。如果其余未完成,此设备将不会在重启后保存密码。通过 ssh 手动执行它就可以了,所以问题不是 cmds,而是脚本的问题。

    #!/usr/bin/expect
    set timeout -1
    #Edit for User
    set user user
    #Edit for Old Password
    set old oldpassword
    #Edit for New Password
    set new newpassword
    #get IP List from iplist.txt
    set f [open "/iplist.txt"]
    set data [read $f]
    close $f

    foreach line [split $data \n] {
            if {$line eq {}} continue
            spawn ssh $user@$line
            expect "assword:"
            send "$old\r"
            sleep 10
            send "passwd $user\r"
            expect "assword:"
            send "$new\r"
            expect "assword:"
            send "$new\r"
            sleep 10
            send "grep -v users.1.password= /tmp/system.cfg > /tmp/system.cfg.new\r"
            sleep 10
            send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print \$2}'` >> /tmp/system.cfg.new\r"
            sleep 10
            send "cp /tmp/system.cfg.new /tmp/system.cfg\r"
            sleep 10
            send "save && reboot\r"
            close
            expect eof
    }

如果设备不响应​​ ssh 或原始密码错误,带有故障保护的完整脚本会大很多。在我弄清楚这部分有什么问题之前,那个是行不通的。我只是将其缩小以找出问题出在哪里。这行似乎也是问题所在,因为它确实在它之前的行上创建了 system.config.new:

            send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print \$2}'` >> /tmp/system.cfg.new\r"

它在 ssh 中是这样工作的:

            send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print $2}'` >> /tmp/system.cfg.new\r"

但是由于 $2 发送了一个错误,然后可以按预期查看。有人告诉我,放置一个 \$2 会使它只对远程 shell 可见。任何帮助都会很棒。

最初它期望“star”而不是 sleep cmds。我一直在这个脚本上尝试大量的东西,一旦我让它运行,就把它合并到我的完整脚本中。我使用 sleep 的原因是因为“star”似乎与输出不匹配,并且在第二次发送 $new/r 时失败。随着睡眠,它使它走得更远。不过,我确实有一个更正。它实际上正在发送“save && reboot\r”。我最终将使用您在我的其他问题中提出的 $prompt 建议来代替睡眠或期待“明星”。对此进行调试时会引发错误:

    send: sending "save && reboot\r" to { exp4 }
    expect: spawn id exp4 not open
        while executing
    "expect eof"
        ("foreach" body line 21)
        invoked from within
    "foreach line [split $data \n] {
            if {$line eq {}} continue
            spawn ssh $user@$line
            expect "assword:"
            send "$old\r"
            sleep 3
            send "passwd $user\r"
            e..."
        (file "./ubnt.sh" line 15)

“save && reboot\r”将在保存设置后退出 ssh 连接,但似乎并没有那么远。 &&有问题吗,也许我需要/&&。

【问题讨论】:

  • 在每个send 命令之后,expect 用于提示。没有它,您就会为不速之客腾出空间,例如此类错误。
  • 添加了更多关于这个的信息,如果你可以看看的话。
  • 我尝试将保存和重启拆分为 2 个发送 cmd,它会保存设置,但在发送重启 cmd 后会出错,而不是重启设备。有什么想法吗?

标签: ssh scripting expect


【解决方案1】:

交互而不是关闭并期望 eof 是我将在完成后使用完整脚本更新的答案。这是有效的 UBNT 密码更改脚本:

    #!/usr/bin/expect
    set timeout 30
    #Edit for User
    set user user
    #Edit for Old Password
    set old oldpassword
    #Edit for New Password
    set new newpassword
    #get IP List from iplist.txt
    set f [open "/iplist.txt"]
    set data [read $f]
    close $f

    foreach line [split $data \n] {
            if {$line eq {}} continue
            spawn ssh $user@$line
            expect {
                    "assword:" {
                            send "$old\r"
                            expect {
                                    "assword:" {
                                                    close
                                                    continue
                                                    }}
                            expect {
                                    "*" {
                                            send "passwd $user\r"
                                            expect "*assword:*"
                                            send "$new\r"
                                            expect "*assword:*"
                                            send "$new\r"
                                            expect "*"
                                            send "grep -v users.1.password= /tmp/system.cfg > /tmp/system.cfg.new\r"
                                            expect "*"
                                            send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print \$2}'` >> /tmp/system.cfg.new\r"
                                            expect "*"
                                            send "cp /tmp/system.cfg.new /tmp/system.cfg\r"
                                            expect "*"
                                            send "save && reboot\r"
                                            interact
                                            continue
                                            }}}}
            expect {
                    "*" {
                            close
                            continue
                            }}
            expect eof
    }

这是 Mikrotik 密码的脚本:

    #!/usr/bin/expect
    set timeout 30
    #Edit for User
    set user user
    #Edit for Old Password
    set old oldpassword
    #Edit for New Password
    set new newpassword
    #get IP List from iplist.txt
    set f [open "/iplist.txt"]
    set data [read $f]
    close $f

    foreach line [split $data \n] {
            if {$line eq {}} continue
            spawn -noecho ssh -q -o "StrictHostKeyChecking=no" $user@$line
            expect {
                    "assword:" {
                            send "$old\r"
                            expect {
                                    "assword:" {
                                                    close
                                                    continue
                                                    }}
                            expect {
                                    "*" {
                                            send "user set $user password=$new\r"
                                            expect ">"
                                            send "quit\r"
                                            close
                                            continue
                                            }}}}
            expect {
                    "*" {
                            close
                            continue
                            }}
            expect eof
    }

Dinesh 提到我不应该在我的期望命令中使用“星号”,并说应该使用:

    set prompt "#|%|>|\\\$ $"

还有:

    expect -re $prompt

我可能会改变。如果无法通过 ssh 访问设备或旧密码不适用于设备,脚本也会移动到列表中的下一个 IP。我计划对两者进行的唯一其他更改是让它创建 3 个日志文件,列出成功的 ips、错误的密码 ips 和无法访问 ips。这应该只是在每个 continue 之前再添加一个命令,但尚未研究如何将变量输出到本地日志文件。

感谢您对此 Dinesh 的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    相关资源
    最近更新 更多