2

另一个问题中,我得到了一个解决方案,以解决我在期望和 if/else 语句中遇到的困境(基本上,我对它们的编写方式缺乏了解)。给我的脚本有一个例外:如果我干净地连接到远程主机,exit则不会发送命令,这将关闭该连接并移动到列表中的下一个主机。

这是脚本的功能部分:

while {[gets $file1 host] != -1} {
    puts $host
    spawn -noecho ssh $host
    expect {
        "continue connecting" {
            send "yes\r"
            expect {
                "current" {
                    send -- $pw2\r
                    exp_continue
                } 
                "New password" {
                    send -- $pw1\r
                    exp_continue
                } 
                "Retype new password" {
                    send -- $pw1\r
                    exp_continue
                }
                msnyder
            }
            send "exit\r"
        }
    }
    interact
}

当我连接到主机时,我希望看到标准的 Linux 提示符:[username@host ~]$。至少,这是我们的标准提示。提示前面有一个横幅。这可能是一个扭结吗?我不这么认为,因为我只是从 RSA 指纹提示符中寻找“继续连接”,并且它位于跨多行的文本中。我认为 expect 足够聪明,可以忽略任何滚动文本,只查看正在寻找输入的提示中的文本。

我考虑将exit命令作为命令的参数传递ssh $host,但期望似乎不喜欢那样。

现在有人可以帮助我exit正确发送命令吗?

更新:我已经exp_internal 1在脚本中添加了选项以查看它在做什么,并且一旦建立 SSH 连接,即使在用户提示下,它似乎也只会匹配“继续连接”。它似乎没有执行“msnyder”的下一个比较。http://pastebin.com/kEGH3yUY

UPDATE2:我正在取得进展。根据下面Glenn Jackman的脚本,我能够让它工作,直到出现密码提示:

set prompt {\$ $}
set file1 [open [lindex $argv 0] r]
set pw1 [exec cat /home/msnyder/bin/.pw1.txt]
set pw2 [exec cat /home/msnyder/bin/.pw2.txt]

while {[gets $file1 host] != -1} {
    puts $host
    spawn -noecho ssh -q $host
    expect {
        "continue connecting" {
            send "yes\r"
            expect {
                "current" {
                    send -- $pw2\r
                    exp_continue
                }
                "New password" {
                    send -- $pw1\r
                    exp_continue
                }
                "Retype new password" {
                    send -- $pw1\r
                    exp_continue
                }
                -re $prompt {
                    send -- exit\r
                    expect eof
                }
            }
        } -re $prompt {
            send -- exit\r
            expect eof
        }
    }
}

我已经明确告诉它两次发送退出命令,而不是尝试 Glenn 使用的短路方法(根据我在他的回答下的评论,它似乎不起作用)。

现在发生的情况是,它将遍历主机列表,向 RSA 指纹提示发送“yes”,然后向命令提示发送“exit”。但是,当它遇到需要设置密码的服务器时,它会停止。它似乎最终超时,然后用下一个主机重新启动。当前密码未发送。

4

2 回答 2

1
# a regular expression that matches a dollar sign followed by a space 
# anchored at the end of the string
set prompt {\$ $}  

while {[gets $file1 host] != -1} {
    puts $host
    spawn -noecho ssh $host
    expect {
        "continue connecting" {
            send "yes\r"
            expect {
                # ...snipped...
                -re $prompt
            }
        }
        -re $prompt
    }
    send -- exit\r
    expect eof
}

如果您匹配“继续连接”或直接登录到提示符,我们已将“退出”移动到将执行它的位置。


不错的答案,但我讨厌看到代码剪切和粘贴。一条评论和一点重构:当您点击“当前”块时,您更改密码但永远不会退出。碰巧每个场景都应该以您看到提示并退出而结束:

while {[gets $file1 host] != -1} {
    puts $host
    spawn -noecho ssh -q $host
    expect {
        "continue connecting" {
            send "yes\r"
            exp_continue
        }
        "current" {
            send -- $pw2\r
            expect "New password"
            send -- $pw1\r
            expect "Retype new password"
            send -- $pw1\r
            exp_continue
        }
        -re $prompt
    }
    send -- exit\r
    expect eof
}

如果您看到“继续连接”,则发送“是”,然后等待看到“当前”或提示。
如果您看到“当前”,则更改密码,然后等待看到提示。
如果您看到提示,则期望注释结束,您要做的下一件事就是退出。

于 2013-09-06T19:42:27.723 回答
1

我整理了答案。在查看下面格伦的脚本之后,我突然想到每个块都是一个单独的 if/else,而我需要密码部分充当单个块,而出口充当其他块。这就是我现在拥有的:

set prompt {\$ $}
set file1 [open [lindex $argv 0] r]
set pw1 [exec cat /home/msnyder/bin/.pw1.txt]
set pw2 [exec cat /home/msnyder/bin/.pw2.txt]

while {[gets $file1 host] != -1} {
    puts $host
    spawn -noecho ssh -q $host
    expect {
        -re $prompt {
            send -- exit\r
            expect eof
        }
        "current" {
                send -- $pw2\r
                expect "New password"
                send -- $pw1\r
                expect "Retype new password"
                send -- $pw1\r
        }
        "continue connecting" {
            send "yes\r"
            expect {
                "current" {
                    send -- $pw2\r
                    expect "New password"
                    send -- $pw1\r
                    expect "Retype new password"
                    send -- $pw1\r
                }
                -re $prompt {
                    send -- exit\r
                    expect eof
                }
            }
        }
    }
}

它解决了四种情况:

  1. 我不必接受 RSA 指纹或更改我的密码。
  2. 我不必接受 RSA 指纹,但必须更改我的密码。
  3. 我必须接受 RSA 指纹并更改我的密码。
  4. 我必须接受 RSA 指纹,但不能更改我的密码。
于 2013-09-07T00:25:03.847 回答