expect
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит
Утилита Expect позволяет создавать программы, ожидающие вопросов от других программ и дающие им ответы. Expect можно сравнить с роботом, который способен заменить пользователя при взаимодействии со сценариями командной строки. Expect — инструмент, основанный на языке Tcl.
Установка
apt-get install expect yum install expect
Использование
#!/usr/bin/expect -f set timeout -1 #Отключение таймаута spawn ./questions #Запуск скрипта questions expect "Hello, who are you?\r" send -- "Im Adam\r" expect "Can I ask you some questions?\r" send -- "Sure\r" expect "What is your favorite topic?\r" send -- "Technology\r" expect eof
Команда | Описание |
---|---|
spawn | запуск процесса или программы. Например, это может быть командная оболочка, FTP, Telnet, ssh, scp и так далее. |
expect | ожидание данных, выводимых программой. При написании скрипта можно указать, какого именно вывода он ждёт и как на него нужно реагировать. |
send | отправка ответа. Expect-скрипт с помощью этой команды может отправлять входные данные автоматизируемой программе. Она похожа на знакомую вам команду echo в обычных bash-скриптах. |
interact | позволяет переключиться на «ручной» режим управления программой. |
Autoexpect позволяет запускать программы, которые надо автоматизировать, после чего записывает то, что они выводят, и то, что пользователь вводит, отвечая на их вопросы. Вызовем autoexpect, передав этой утилите имя нашего скрипта:
$ autoexpect ./questions
CGP
#!/usr/bin/expect set cmd [lindex $argv 0]; spawn telnet localhost 106 expect "200" { send "USER postmaster\n" } expect "300" { send "PASS Pa\$\$w0rd\n" } expect "200" { send "$cmd\n\n" } expect "200" {} sleep 1 send "QUIT\n" send_user "\n" exit 0
Asterix
#!/usr/bin/expect set username "admin" set secret "admin" set host "127.0.0.1" set port "5038" set channel [lindex $argv 0]; set num [lindex $argv 1]; set name [lindex $argv 2]; send_user "Args: $channel $num $name\n" spawn telnet $host $port expect "Manager" { send "Action: Login\n" send "Username: $username\n" send "Secret: $secret\n\n" } expect "Response: Success" { send "Action: Originate\n" send "Channel: SIP/$channel\n" send "Context: default\n" send "Exten: $num\n" send "Callerid: $name<$num>\n" send "Priority: 1\n\n" } sleep 1 send "Action: Logoff\n\n" exit 0
Docker
#!/usr/bin/expect set email [lindex $argv 0]; set password [lindex $argv 1]; spawn docker exec -it greenlight-v2 bash send "\n" expect "bash*#" {send "bundle exec rails c\n"} expect "irb*>" { send "User.find_by(email: \"$email\").update_attribute(:password,\"$password\")\n" } expect "irb*>" { send "exit\n" } expect "bash*#" { send "exit\n" } send_user "\n" exit 0