2009-10-08 7 views
17

となるようにTELNETセッションへのログインを自動化する必要がありますが、同じユーザー名に対して複数のパスワードを処理する必要があります。'expect'内の条件文を使用

  1. オープンTELNETセッションをIP
  2. 送信ユーザー名
  3. へ送るパスワードを
  4. 間違ったパスワードを:

    ここで私が作成する必要が流れですか?何が価値があるために...

  5. が正常にログインしている必要があります
  6. この時点で、その後別のパスワード、再び

を同じユーザー名を送信し、ここで私がこれまで持っているものです:

#!/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の冒険から、は、が暗い芸術のようだと思っています。この問題の助けを借りて誰にも事前に感謝します!

+0

私は私の答えに多くの情報を追加しました。 – tvanfosson

答えて

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とパスワードのペアがどのシステムに対応しているかを知る必要があります。どのユーザーID /パスワードのペアがどのシステムにあるかを調べ、その情報を抽出して正しいものを使うだけの方がよいでしょう。

あなたは明らかに私のアドバイスが嫌いなので、wikipedia pageを見て、成功すれば0を返し、期待値がタイムアウトしたら1を返すようにすることをお勧めします。これにより、入力されたパスワードが失敗したとき(即時の予想時間切れ)を検出して再試行できます。これが参考になった場合は、編集したダウンノートを削除することができます。

振り返ってみると、パスワードが変更された場合にログインに失敗したことを検出したいので、マップと一緒にこれを行うことをお勧めします。

+0

downvote申し訳ありません。私は長い間電話をかけていましたが、理由を説明するために投稿を入力しなくても、まだ答えが出ていないことを素早く示したいと思っていました。 特定のデバイスで使用されているパスワードを文書化する信頼できる方法があれば、私は確かに条件付きメソッドを使用しません。コントロール外のファームウェアリビジョンで変更することができるので、試してみる準備が整ったパスワードのリストを手に入れることができます。 私は必要なことを理解しています - 条件文を使って答えに作用します - 私はそれをどうやって行うのか分かりません。 :) – shuckster

+0

あなたが今編集した投票を削除することができます - それは追加情報が役立つか、少なくとも投稿が役に立たないようにしていない場合です。あなたが答えを受け入れない限り、人々は答えを続ける可能性が高いですが、パスワードの追跡が難しい理由に関する情報であなたの質問を更新したいかもしれません。 – tvanfosson

10

私は解決策を見つけました。 TCL構文を使用して、私が慣れていない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

+0

私はExpectに新しいです、期待{"case1 "{...}" case2 "{...}" case3 "{...}}、これはC++のようなswitch case文ですか?ありがとう –

+0

@ B.Mr.W。はい、それを外側の '' '}' '' 'で使用すると、個々の' '' if'''ステートメントではなく、 – eulerworks