2009-10-08 105 views
17

我需要使用期望自动登录到TELNET会话,但是我需要照顾同一用户名的多个密码。在'expect'中使用条件语句

这是我需要创建流程:

  1. 打开Telnet会话的IP
  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" 

不用说,这不起作用,也不看起来非常漂亮。从我的冒险与谷歌期待似乎是一个黑暗艺术的东西。在此先感谢任何人提供有关此事的协助!

+0

我已将更多信息添加到我的答案中。 – tvanfosson 2009-10-08 15:40:35

回答

31

不得不为所有期望的程序员推荐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\n结束不\r

您没有逃脱>字符在您的提示:这不是特殊的Tcl的。

-1

如果您知道用户ID和密码,那么您还应该知道哪些用户ID /密码对与哪些系统对齐。我认为你最好保留一张使用哪个用户名/密码对与哪个系统的映射,然后提取该信息并简单地使用正确的映射。所以 - 因为你显然不喜欢我的建议,那么我建议你看看wikipedia page并实现一个过程,如果成功则返回0,如果期望超时则返回1。这将允许您检测提供的密码何时失败 - 提示期望超时 - 然后重试。如果这有帮助,那么现在可以删除已经编辑它的downvote。

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

+0

对不起。我打了一个长长的电话,想要一个快速的方式来表明,如果没有输入帖子来解释原因,我还没有答案。 无论如何,我肯定不会使用条件方法,如果我有一个可靠的方式来记录某些设备上使用的密码。它可以在我控制范围之外的固件版本之间进行更改,所以我所能做的就是准备好一个可以尝试的密码列表。 我明白我需要做什么 - 使用条件语句并对答案采取行动 - 我只是不知道该怎么做。 :) – shuckster 2009-10-08 16:24:06

+0

您现在可以删除我已编辑的投票 - 也就是说,如果附加信息有帮助或至少不会使帖子无用。只要你不接受答案,人们很可能会继续添加答案 - 尽管你可能想要更新你的问题,并提供关于为什么跟踪密码很难的信息。 – tvanfosson 2009-10-08 16:42:09

10

随着一阵抨击,我找到了解决方案。原来,期望使用,我不是与所有熟悉的一个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 

希望这将是有用的人。

+1

我使用了类似的SSH解决方案,但是从密码文件'〜/ .ssh/ssh-passwords'中读取密码。主机名和用户名从我的'〜/ .ssh/config'文件中读取。所以运行:'[cssh](https://github.com/DavidGamba/bin/blob/master/cssh)server1'将扩展到[email protected] – DavidG 2013-07-30 16:59:59

+0

我是新来的期待,expect {“case1 “{...}”case2“{...}”case3“{...}},这是一种类似C++的switch case语句吗?谢谢 – 2013-10-10 21:35:17

+0

@ B.Mr.W。是的,在外面使用'''''''基本上使它成为一个通过而不是单个'''if'''语句 – eulerworks 2017-05-02 00:09:00