Использование условных операторов внутри «ожидаемо» - PullRequest
24 голосов
/ 08 октября 2009

Мне нужно автоматизировать вход в сеанс TELNET, используя ожидайте , но мне нужно позаботиться о нескольких паролях для одного имени пользователя.

Вот поток, который мне нужно создать:

  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"

Само собой разумеется, что это не работает, и при этом это не выглядит очень симпатичным. Из моих приключений с Google ожидаю, что кажется чем-то вроде мрачного искусства. Заранее спасибо всем за помощь в этом вопросе!

Ответы [ 3 ]

36 голосов
/ 08 октября 2009

Нужно рекомендовать книгу 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 возвращается к началу ожидаемого блока - это похоже на оператор "redo".

Обратите внимание, что send_user оканчивается на \n, а не \r

Вам не нужно экранировать символ > в приглашении: он не является особенным для Tcl.

11 голосов
/ 08 октября 2009

С небольшим избиением я нашел решение. Оказывается, что ожидаемый использует синтаксис 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

Надеюсь, это будет полезно другим.

0 голосов
/ 08 октября 2009

Если вам известны идентификаторы и пароли пользователей, вам также следует знать, какие пары идентификаторов пользователей и паролей соответствуют каким системам. Я думаю, что вам лучше сохранить карту, в которой используется пара идентификаторов пользователей и паролей, с какой системой извлекать эту информацию и просто использовать правильную.

Итак, поскольку вам явно не нравится мой совет, я предлагаю вам взглянуть на страницу википедии и реализовать процедуру, которая возвращает 0 в случае успеха и 1, если время ожидания истекло. Это позволит вам определить, когда указан неверный пароль - время ожидания запроса истекло, - и повторить попытку. Если это полезно, вы можете удалить свое голосование теперь, когда я его отредактировал.

В ретроспективе вы, вероятно, все равно захотите сделать это вместе с картой, поскольку вы захотите обнаружить неудачный вход в систему, если пароль был изменен.

...