web-dev-qa-db-ja.com

「expect」内で条件ステートメントを使用する

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はダークアートのようなもののようです。問題の支援のために誰にでも事前に感謝します!

25
shuckster

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

send_user\nではなく\rで終わることに注意してください

プロンプトで>文字をエスケープする必要はありません。Tclにとって特別なものではありません。

38
glenn jackman

少したたいて、解決策を見つけました。 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

これが他の人に役立つことを願っています。

11
shuckster