Поиск по сайту:

Автоматизируйте ввод в сценарии Linux с помощью команды expect


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

Автоматизация означает эффективность

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

Сценарий многословной или утомительной работы дает вам возможность запускать эту задачу, когда офис закрыт, или в самые тихие периоды работы 24/7. Скрипты также обеспечивают повторяемость. Они не забудут выполнить шаг, сколько бы раз их ни просили выполнить одну и ту же скучную работу.

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

В Linux есть команда yes, которая отправляет в окно терминала поток символов «y» или любую другую указанную пользователем строку. Если программа ожидает ответа на вопрос «да» или «нет», ей будет принудительно передан один из символов «y». Он примет его как ввод и сможет продолжить. Вам нужно направить вывод от yes в скрипт.

yes | script.sh

Возможно, вы не хотите отправлять утвердительный ответ. Возможно, вам нужно сказать «нет». Вы также можете сделать это, используя команду yes. Вы можете отправить любую фразу, которая вам нравится, вы не ограничены ответами типа «y», «y», «Yes», «n», «N» или «No».

Возможно, вам нужно отправить «r» для переустановки в приглашение «install/upgrade/reinstall [i/u/r]».

yes r

Команда yes не справляется, если ей нужно предоставить более одного типа ответа. В этой ситуации нам нужно использовать expect .

Установка ожидаемой команды

Мы протестировали expect на Ubuntu, Fedora и Manjaro. Пакета не было в комплекте с этими дистрибутивами, поэтому его пришлось установить. В Ubuntu введите:

sudo apt install expect

В Fedora вам нужна команда:

sudo dnf install expect

В Manjaro мы используем pacman:

sudo pacman -Sy expect

Как ожидать работы

Команда expect позволяет вам управлять двумя концами диалога между вашим набором подготовленных ответов и программой или сценарием, которым вы будете их отправлять. Вы делаете это, создавая «ожидаемый» сценарий, который отслеживает подсказки в основном сценарии и отправляет соответствующий ответ для каждого из них.

Допустим, у вас есть сценарий резервного копирования, который запрашивает имя исходного каталога и имя целевого каталога. Затем он делает копию файлов исходного каталога в целевом каталоге. Без битов, которые копируют файл, ваш скрипт может выглядеть примерно так:

#!/bin/bash

echo "Directory to backup?"
read source_directory

echo "Backup location?"
read target_directory

echo
echo "Target directory:" $target_directory

Все, что делает этот скрипт, это запрашивает пути к двум каталогам. Он выводит целевой каталог в окно терминала, чтобы мы могли видеть, что он получил ответ от expect и смог его правильно прочитать.

Чтобы обеспечить вторую половину разговора, мы создаем «ожидаемый сценарий». По соглашению они имеют расширение «.exp». Этот пример будет работать с нашим скриптом «backup.sh».

#!/usr/bin/expect -f

set timeout -1

spawn ./backup.sh

expect "Directory to backup?r"
send -- "/home/dave/Documents/r"

expect "Backup location?r"
send -- "/media/dave/external/backupr"

expect eof

Здесь показаны основные три команды в сценариях ожидания: команды spawn, expect и send.

Первое, на что следует обратить внимание, это то, что shebang относится к expect, а не к bash. Флаг -f (файл) указывает ожидать, что ответы поступают из файла.

Мы эффективно отключаем тайм-ауты, устанавливая их на бесконечность с -1.

Команда spawn запускает сценарий резервного копирования.

Мы знаем два вопроса, которые задаст нам скрипт «backup.sh». Для каждого вопроса мы создаем строку «ожидание». Они содержат текстовое приглашение, которое будет отправлено в окно терминала сценарием «backup.sh». Это то, на что будет обращать внимание программа expect. Когда expect видит приглашение, текст в строке send возвращается в сценарий «backup.sh».

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

Сделайте оба скрипта исполняемыми:

chmod +x backup.sh
chmod +x backup.exp

И используйте сценарий «backup.exp», чтобы запустить весь процесс.

./backup.exp

Вы можете увидеть две подсказки от «backup.sh» и ответы от «backup.exp».

Это будет невероятно быстро

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

Текст в строках expect должен точно соответствовать подсказкам скрипта, который вы автоматизируете. Опечатки и неправильная формулировка приведут к тому, что подсказка будет пропущена, и автоматический процесс остановится. Если вы все еще разрабатываете или настраиваете сценарий, который пытаетесь автоматизировать, формулировка подсказок и их порядок в сценарии, скорее всего, изменятся. Обновления сценариев или программ могут изменять, удалять или добавлять подсказки. Отслеживание изменений и их воспроизведение в ожидаемом сценарии становится утомительным и подверженным ошибкам.

Самый удобный способ создать сценарий ожидания — использовать autoexpect. Он устанавливается вместе с expect. Мы можем указать autoexpect отслеживать наше реальное взаимодействие со сценарием или программой и создать для нас ожидаемый файл.

Возможно, в сгенерированном ожидаемом файле нужно будет что-то подправить, но это намного быстрее, чем писать его вручную. Например, если вы что-то неправильно напечатаете в своем сеансе, когда autoexpect отслеживает вас, все неправильные нажатия клавиш, а также ваше редактирование и возврат для их исправления будут зафиксированы. Чтобы убрать это, просто удалите этот раздел и введите правильный текст.

Использование автоожидания

Использовать autoexpect очень просто. Мы используем флаг -f (имя файла), чтобы сообщить ему имя ожидаемого файла, который он должен создать, и программу или сценарий, который мы хотим, чтобы он запускал. Подсказки процесса и наши ответы записываются и отправляются в ожидаемый файл. Приятно отметить, что autoexpect делает ожидаемый файл исполняемым для нас.

Допустим, мы часто используем rsync для отправки файлов с одного компьютера в каталог на другом компьютере по сети. Мы будем использовать autoexpect для создания ожидаемого файла этого процесса.

Наша командная строка выглядит так. Первая команда — autoexpect , за которой следует флаг -f и имя ожидаемого файла, который мы хотим создать. В данном случае это «send-pics.exp».

Остальная часть команды представляет собой обычную команду rsync. Поскольку rsync использует протокол SSH для удаленного подключения к целевому компьютеру, нам потребуется указать пароль для учетной записи пользователя «dave» на целевом компьютере.

autoexpect -f send-pics.exp rsync -rasv ~/Pictures/raw/ dave@nostromo.local:/home/dave/raw/

Когда мы выполняем эту команду, запускается rsync, и нам предлагается ввести пароль для учетной записи пользователя dave на удаленном компьютере. После ввода некоторые файлы отправляются на удаленный компьютер, rsync разрывает соединение, и процесс завершается.

Нам сообщают, что файл «send-pics.exp» создан. Давайте взглянем:

ls -l send-pics.exp

Он действительно был создан и является исполняемым. Мы можем запустить его, вызвав его по имени:

./send-pics.exp

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

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

Подожди, мой пароль!

Вы должны знать, что любые пароли или любая другая конфиденциальная информация, собранная во время сеанса autoexpect, сохраняются в виде обычного текста в сгенерированном сценарии ожидания. Пароли никогда и нигде не должны быть написаны открытым текстом. Для соединений SSH лучше использовать ключи SSH и схему аутентификации без пароля.

Очевидно, что это не поможет, если вы не используете SSH.

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

interact ++ return

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

./send-pics.exp

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

Другой способ решения проблемы заключается в следующем:

  • Измените права доступа к файлу в сценарии ожидания с помощью chown на 740, -rwxr-x---.
  • Используйте chmod, чтобы изменить владельца группы сценария ожидания на доверенную группу.
  • Создайте обычный сценарий, запускающий ожидаемый сценарий. Установите, что этот файл также принадлежит доверенной группе. Установите для этого разрешения 2751, -rwxr-s--x.
  • При этом создается сценарий запуска, который может прочитать и выполнить любой, который находится в той же доверенной группе, что и ожидаемый сценарий, и с установленным битом setgid. Независимо от того, кто запускает этот сценарий, его эффективной группой будет доверенная группа, а не группа человека, запускающего сценарий. Таким образом, этот скрипт всегда сможет запустить ожидаемый скрипт.
  • При этом ожидаемый сценарий, содержащий пароль, недоступен никому, кроме вас.

Вы можете ожидать великих дел

Здесь достаточно, чтобы вы начали работать, но ожидать гораздо больше, чем те области, которые мы рассмотрели. Страница руководства expect содержит более 1700 строк!

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