期望脚本错误

Error On Expect Script

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

    #!/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 }'` >> /tmp/system.cfg.new\r"

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

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

    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 连接,但似乎没有那么远。 && 有问题吗,也许我需要 /&&.

交互而不是关闭并期待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 提到我不应该在我的 expect 命令中使用 "star" 并说应该使用:

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

并且:

    expect -re $prompt

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

感谢您对此 Dinesh 的帮助。