32

我需要使用expect自动登录到 TELNET 会话,但我需要处理同一个用户名的多个密码。

这是我需要创建的流程:

  1. 打开到 IP 的 TELNET 会话
  2. 发送用户名
  3. 发送密码
  4. 密码错误?再次发送相同的用户名,然后发送不同的密码
  5. 此时应该已经成功登录...

对于它的价值,这是我到目前为止所得到的:

#!/usr/bin/expect
spawn telnet 192.168.40.100
expect "login:"
send "spongebob\r"
expect "password:"
send "squarepants\r"
expect "login incorrect" {
  expect "login:"
  send "spongebob\r"
  expect "password:"
  send "rhombuspants\r"
}
expect "prompt\>" {
  send_user "success!\r"
}
send "blah...blah...blah\r"

不用说这不起作用,而且看起来也不是很漂亮。从我与 Google 的冒险经历来看,expect似乎是一种黑暗艺术。提前感谢任何人在此事上的帮助!

4

3 回答 3

44

必须为所有期望程序员推荐Exploring Expect这本书——非常宝贵。

我已经重写了你的代码:(未经测试)

proc login {user pass} {
    expect "login:"
    send "$user\r"
    expect "password:"
    send "$pass\r"
}

set username spongebob 
set passwords {squarepants rhombuspants}
set index 0

spawn telnet 192.168.40.100
login $username [lindex $passwords $index]
expect {
    "login incorrect" {
        send_user "failed with $username:[lindex $passwords $index]\n"
        incr index
        if {$index == [llength $passwords]} {
            error "ran out of possible passwords"
        }
        login $username [lindex $passwords $index]
        exp_continue
    }
    "prompt>" 
}
send_user "success!\n"
# ...

exp_continue循环回到期望块的开头——这就像一个“重做”语句。

注意send_user\nnot结尾\r

您不必>在提示符中转义字符:它对 Tcl 来说并不特殊。

于 2009-10-08T17:12:19.937 回答
11

经过一番抨击,我找到了解决方案。事实证明,expect 使用了我完全不熟悉的 TCL 语法:

#!/usr/bin/expect
set pass(0) "squarepants"
set pass(1) "rhombuspants"
set pass(2) "trapezoidpants"
set count 0
set prompt "> "
spawn telnet 192.168.40.100
expect {
  "$prompt" {
    send_user "successfully logged in!\r"
  }
  "password:" {
    send "$pass($count)\r"
    exp_continue
  }
  "login incorrect" {
    incr count
    exp_continue
  }
  "username:" {
    send "spongebob\r"
    exp_continue
  }
}
send "command1\r"
expect "$prompt"
send "command2\r"
expect "$prompt"
send "exit\r"
expect eof
exit

希望这对其他人有用。

于 2009-10-08T17:14:02.100 回答
-1

如果您知道用户 ID 和密码,那么您还应该知道哪些用户 ID/密码对与哪些系统一致。我认为你最好维护一张用户标识/密码对与哪个系统一起使用的地图,然后提取该信息并简单地使用正确的信息。

所以 - 既然您显然不喜欢我的建议,那么我建议您查看维基百科页面并实施一个过程,如果成功则返回 0,如果期望超时则返回 1。这将允许您检测提供的密码何时失败(提示预期超时)并重试。如果这有帮助,您可以在我编辑后删除您的反对票。

回想起来,您可能希望与地图一起执行此操作,因为如果更改密码,您希望检测登录失败。

于 2009-10-08T15:19:26.123 回答