💣 Как автоматизировать интерактивные команды cli с помощью expect

by itisgood

Expect – это бесплатная утилита с открытым исходным кодом, которую мы можем использовать для автоматического ответа на интерактивные запросы в соответствии со скриптами, включающими команды expects/sends.

В этом руководстве мы узнаем, как установить expect в наиболее распространенных дистрибутивах Linux, как использовать ее для автоматического ответа на интерактивные запросы и как генерировать скрипты expect с помощью autoexpect.

Установка expect

Хотя expect есть в репозиториях всех основных дистрибутивов Linux, по умолчанию она обычно не установлена.

Чтобы установить утилиту на Fedora и другие дистрибутивы семейства Red Hat, такие как Rocky Linux, мы можем воспользоваться менеджером пакетов dnf:

$ sudo dnf install expect

Чтобы установить пакет на Debian или другие дистрибутивы, основанные на нем, вместо этого мы можем выполнить команду:

$ sudo apt-get update && sudo apt-get install expect

Expect также доступен в репозитории Archlinux «Extra».

Мы можем установить его с помощью pacman:

$ sudo pacman -Sy expect

Пример использования Expect

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

В других случаях, по разным причинам, эти опции отсутствуют: вот тут-то и пригодится expect.

Создавая специальные сценарии expect, мы можем автоматизировать выполнение команд, требующих взаимодействия с пользователем, предоставляя предопределенные ответы на ожидаемые подсказки.

Давайте рассмотрим несколько базовых примеров.

Здесь мы создаем скрипт, который задает некоторый вопрос (имя, страна и адрес электронной почты):

#!/bin/bash 
read -p "What is your name? " name 
read -p "What is your country? " country 
read -p "Enter your email address: " email

Скрипт тривиален, не выполняет никакой проверки данных, но для нашей цели этого достаточно.

Мы сохраняем его под именем «prompts.sh» и даем ему права на выполнение:

$ chmod +x prompts.sh

Как только мы его выполним, как и ожидалось, он предложит нам предоставить запрашиваемую информацию:

$ ./prompts.sh
What is your name? Egidio
What is your country? Italy
Enter your email address: nomail@gmail.com

Как только мы ответим на первую подсказку, созданную скриптом, и нажмем «Enter», появится вторая, и так далее.

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

#!/bin/expect 
spawn ./prompts.sh 
expect "What is your name?" { send "Egidio\n" }
expect "What is your country?" { send "Italy\n" }
expect "Enter your email address" { send "nomail@gmail.com\n" }
expect EOF

Первое, что вы должны заметить, это то, что в качестве интерпретатора скрипта мы использовали /bin/expect, а не /bin/bash: это нужно для того, чтобы не передавать скрипт в качестве аргумента программе expect (не путайте с именем команды, которую мы можем использовать в скрипте), каждый раз, когда мы хотим его вызвать.

В нашем тривиальном скрипте мы использовали три команды: spawn, expect и send.

Первая, spawn, запускает новый процесс и подключает дескрипторы файлов стандартного вывода, стандартного ввода и стандартной ошибки последнего к expect, чтобы он мог анализировать сообщения программы и выполнять предусмотренные скриптом действия.

Команда expect ждет, пока определенный шаблон не совпадет с выводом исполняемого файла, запущенного командой spawn.
В приведенном выше примере совпадение может произойти в любом месте вывода.
Если вывод команды был: «Tell me, what is your country?», шаблон все равно бы совпал.
Чтобы обеспечить наиболее строгое соответствие, мы могли бы использовать якоря регулярных выражений: ^ и $.
Они соответствуют, соответственно, началу и концу потока данных.
Если шаблон не совпадает с выводом, а таймаут истек, команда expect возвращается, и выполнение crhbgnf продолжается до следующей инструкции.
По умолчанию тайм-аут составляет 10 секунд; мы можем изменить его, присвоив переменной «timeout» другое значение:
set timeout 20

В приведенном выше примере мы установили тайм-аут в 20 секунд; использование значения -1 полностью отключает тайм-аут, так что expect будет ждать бесконечно, а значение 0 вызывает противоположное поведение: expect не ждет вообще.

Последняя команда, которую мы использовали, – send.

Команда send отправляет процессу строку.

Обратите внимание, что мы включили в строку символ \n (конец строки), поскольку по умолчанию форматирование не применяется.

В последней строке сценария вместо конкретного сообщения мы сопоставили его с EOF (End Of File).

Мы сохраняем скрипт под именем prompts.exp (расширение «.exp» – это просто условность) и делаем его исполняемым.

Наконец, мы запускаем его.

Вот его вывод:

$ ./script.exp 
spawn ./prompts.sh
What is your name? Egidio
What is your country? Italy
Enter your email address: nomail@gmail.com

Автогенерация скриптов expect с помощью autoexpect

Autoexpect – это утилита, которая поставляется вместе с expect: с ее помощью мы можем генерировать скрипты expect как результат интерактивной сессии.

Вместо того чтобы писать expect-скрипт вручную, мы можем использовать autoexpect для запуска команды, требующей взаимодействия с пользователем, например

$ autoexpect ./prompts.sh

Скрипт , который мы предоставляем в качестве аргумента autoexpect, запускается; он требует нашего взаимодействия, как это обычно и происходит.

Однако после выхода из сценария генерируется сценарий ожидания: script.exp.

При выполнении он воспроизведет действия, которые мы выполняли в интерактивном режиме.

Заключение

В этом руководстве мы познакомились с основами использования expect для автоматизации интерактивных команд. Мы рассмотрели базовый пример написания скрипта expect, используя команды spawn, expect и send.

Наконец, мы увидели, как можно автоматически генерировать сценарий expect с помощью утилиты autoexpect.

Здесь мы едва коснулись поверхности того, чего можно достичь с помощью скриптов expect.

см. также:

 

You may also like

Leave a Comment