2009-10-08 47 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