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期待ブロックの先頭にループバックします。これは「やり直し」ステートメントのようなものです。

notでsend_user終わることに注意してください\n\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とパスワードのペアがどのシステムと連携しているかについても知っておく必要があります。どのユーザーIDとパスワードのペアがどのシステムに対応しているかのマップを維持し、その情報を抽出して、正しい情報を使用する方がよいと思います。

つまり、私のアドバイスが明らかに気に入らないので、ウィキペディアのページを見て、成功した場合は0を返し、期待がタイムアウトした場合は1を返すプロシージャを実装することをお勧めします。これにより、提供されたパスワードが失敗したことを検出し(プロンプトの期待がタイムアウトします)、再試行できます。これが役に立ったら、私が編集したので、あなたはあなたの反対票を削除することができます。

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

于 2009-10-08T15:19:26.123 に答える