какой интерпретер запускает expect скрипты
Почему мой сценарий expect не работает в строке 1?
самая первая строка моего сценария expect терпит неудачу. Вот все содержимое моего скрипта, и он терпит неудачу:
как мой ответ. Expect фактически установлен и находится в /usr/bin/, и я запускаю это из root. У меня нет дополнительных пробелов или строк перед знаком#. Конечно, изначально было больше сценария, но он терпит неудачу, прежде чем он доберется до хорошего материала.
4 ответов
попробовал, и вот результат:/usr/bin / expect^M: плохой интерпретатор
возможно ли, что там есть новая строка Windows («^M»), которая запутывает сценарий? Вы можете попробовать «od», чтобы увидеть, какие символы новой строки после» expect «и» tofromdos » или редактора(например, emacs в режиме hexl), чтобы удалить его. Дополнительные сведения см. На страницах man.
Я имел эту проблему и нашли я не ожидал установлен переводчик! Как ни странно, если вы запустили команду в оболочке, она сработала. Однако через скрипт оболочки я получил ошибку: / usr/bin / expect: плохой интерпретатор: нет такого файла или каталога.
я исправил это, просто установив интерпретатор Expect. Выбранное имя пакета:ожидать libtcl8.6
Я действительно не знаю, ожидаю, если честно, но когда я запускаю это в своей системе, он» работает » нормально. Ничего не происходит, но этого я и ожидал. Я не получаю никакого сообщения об ошибке. Согласно man page,
— это правильный способ запуска скрипта. Ожидать потом хлебает копирование скрипта как cmdfile.
способ, которым я получил его, чтобы воспроизвести проблему, состоял в том, чтобы фактически поставить A ^M в конце строки вместо нормальной новой строки (см. ответ и это побудило меня попробовать). Я уверен, что команда vim: set list покажет любые нечетные символы.
Моя внешняя память
В жизни сетевого инженера (да и не только), наступает такой момент, когда некоторые рутинные операции надоедает выполнять, и хочется их оптимизировать. В один прекрасный день я понял, что каждый раз когда мне нужно авторизоваться на коммутаторе, то набирать логин\пароль, а затем ещё пароль на enable мне надоело. Поэтому данное действие было решено как-то оптимизировать. Взяв бутылочку пенного я сел за «работу»..
В компании где я работаю, по определённым обстоятельствам авторизация на коммутаторах\роутерах\DSLAM и прочем оборудовании происходит не по ssh, а по telnet. Средствами самого telnet возможности передать логин\пароль нет, поэтому поиск с попутным распитием алкоголя продолжился, и остановился на утилите expect.
Expect — это утилита, которая парсит потоковый вывод консольных программ, и в ответ на них отправляет какой либо заранее предусмотренный «ответ». Например, при подключении к ftp серверу, ожидаем получить запрос на ввод пароля, и при его получении — отправляем его.
Для моей задачи expect подошёл идеально. Да и как оказалось, у одного из коллег уже был небольшой expect скрипт для этих целей, который, правда, не совсем подходил мне, но для ознакомления с expect пришёлся весьма кстати.
Чтобы более или менее понять, рассмотрим для начала небольшой expect скрипт, который авторизует пользователя на ftp сервере:
Если что-то во время выполнения скрипта идёт не так, то можно посмотреть более подробно, какие данные получает expect, нашёл ли совпадения, и что посылает в ответ. Для этого надо добавить exp_internal 1 в код скрипта:
Видно, что после отправки пароля, ftp сервер снова его спрашивает. Значит, ошиблись где-то в логине или пароле.
Теперь пример сложнее. Скрипт выше делает то, что нам нужно в данном случае, но в нём есть некоторые недостатки: для каждого хоста необходимо создавать новый скрипт; если сайт недоступен, то скрипт будет вести себя весьма странно.
Исправим эти недостатки немного модифицировав его (для удобства добавленные\изменённые участки кода прокомментированы):
Всё бы хорошо, но всё ещё чего-то не хватает скрипту, что-то не так… И правда: проверка таким образом доступности ftp сервера не самая лучшая идея.
Хороший выход из данной ситуации — это нужную нам часть вынести в bash скрипт, проверку доступности выполнять обычным пингом, а количество аргументов средствами самого bash:
Комментировать часть скрипта написанного на bash я не буду — для этого есть ресурсы лучше. Какой либо особой магии здесь нет. Просто проверяем количество аргументов переданных скрипту, доступность сервера для подключения и если всё в порядке — запускаем expect передавая ему команды. expect eof здесь нужен чтобы скрипт не завершался сразу после выполнения.
Раз уж мы заговорили про использование expect в bash, то коснёмся и сбора данных. Для примера давайте представим, что есть сферический ftp сервер в вакууме, с которого зачем-то нужно раз в сутки собирать список имеющихся директорий. Ситуация надуманная, но для примера подойдёт:
Пример принципиально не сильно отличается от предыдущего. В переменной DIRLIST запускаем expect и построчно выполняем скрипт. Следует обратить внимание, что так как мы запустили expect внутри bash, то надо дополнительно экранировать посылаемые и ожидаемые данные. Далее работаем с полученными результатами как с простым текстом.
Для моих нужд в результате получился такой скрипт:
Доступность хоста проверяется с помощью fping, т.к. он позволяет задать меньший timeout ответа от хоста. После всех необходимых действий с входными данными, скрипт запускает gnome-terminal, в нём интерпретатор expect которому передаётся скрипт в виде переменной commands.
Использование expect в bash скриптах
Тяжело объяснить без примера. О примерах использвания expect дальше и пойдет речь. Планируется сборная статья, которая будет пополнятся разнообразными примерами использования expect.
Есть два варианта, по аналогии с perl/python :
«\r» в конце строки означает отправку команды (нажатие клавиши Enter).
Основная структура скрипта:
Если Вы хотите передать в скрипт какие-то параметры и использовать их в работе воспользуйтесь директивой set :
Используйте interact в конце, если по завершению выполнения всех send’ов сесия должна оставаться активной. Удобно для автоматизации при работе с ssh.
Пример 1: SSH
Стандартному линуксовому ссш клиенту можно стравить имя пользователя и ipадрес сервера как аргуметы, но пароль ему нельзя передать. Следующие скрипт принимает в качестве аргументов имя пользователя и пароль, дальше подключается с ними к серверу 192.168.1.10 и выполняет там cat /etc/issue
Выполнить его можно так:
Согласитесь, если у Вас есть список серверов, с паролями и логинами, то можно сгенерировать батч и автоматизировать выполнение определенной команды на всех серверах.
Весь вывод можно записать в лог использовав следующую конструкцию в начале файла:
Немаловажным является время выполнения. Я не помню значение по умолчанию, но хорошей практивой является установка таймаута на выполнение:
Пример 2: FTP
Допустим нужно загрузить содержимое 10-ти ftp серверов в один каталог на сервере. Представьте использование 10-ти комбинаций логинов, паролей и адрдресов в lftp. Представили? Страшно?
Я вышел из ситуации следующим образом:
С помощью rsync загружаем выбраные папки с сервера
Нужно стянуть папки этих сайтов на новый сервер.
В подобных случаях я инициализирую в bash список с названием list:
Дальше цыклом for перебираю эллементы списка:
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит
В прошлый раз мы говорили о методике разработки bash-скриптов. Если же суммировать всё, что мы разобрали в предыдущих десяти материалах, то вы, если начинали читать их, ничего не зная о bash, теперь можете сделать уже довольно много всего полезного.
Сегодняшняя тема, заключительная в этой серии материалов, посвящена автоматизации работы с интерактивными утилитами, например, со скриптами, которые, в процессе выполнения, взаимодействуют с пользователем. В этом деле нам поможет expect — инструмент, основанный на языке Tcl.
Expect позволяет создавать программы, ожидающие вопросов от других программ и дающие им ответы. Expect можно сравнить с роботом, который способен заменить пользователя при взаимодействии со сценариями командной строки.
Основы expect
Если expect в вашей системе не установлен, исправить это, например, в Ubuntu, можно так:
В чём-то вроде CentOs установка выполняется такой командой:
Expect предоставляет набор команд, позволяющих взаимодействовать с утилитами командной строки. Вот его основные команды:
Автоматизация bash-скрипта
Напишем скрипт, который взаимодействует с пользователем и автоматизируем его с помощью expect. Вот код bash-скрипта questions :
Теперь напишем expect-скрипт, который запустит скрипт questions и будет отвечать на его вопросы:
В последней команде expect ожидает признака конца файла, скрипт, дойдя до этой команды, завершается.
Теперь пришло время всё это опробовать. Сделаем answerbot исполняемым файлом:
Expect-скрипт отвечает на вопросы bash-скрипта
Как видно, expect-скрипт верно ответил на вопросы bash-скрипта. Если на данном этапе вы столкнулись с ошибкой, вызванной тем, что неправильно указано расположение expect, выяснить его адрес можно так:
Обратите внимание на то, что после запуска скрипта answerbot всё происходит в полностью автоматическом режиме. То же самое можно проделать для любой утилиты командной строки. Тут надо отметить, что наш bash-скрипт устроен очень просто, мы точно знаем, какие именно данные он выводит, поэтому написать expect-скрипт для взаимодействия с ним несложно. Задача усложняется при работе с программами, которые написаны другими разработчиками. Однако, здесь на помощь приходит средство для автоматизированного создания expect-скриптов.
Autoexpect — автоматизированное создание expect-скриптов
Autoexpect позволяет запускать программы, которые надо автоматизировать, после чего записывает то, что они выводят, и то, что пользователь вводит, отвечая на их вопросы. Вызовем autoexpect, передав этой утилите имя нашего скрипта:
В этом режиме взаимодействие с bash-скриптом ничем не отличается от обычного: мы сами вводим ответы на его вопросы.
Запуск bash-скрипта с помощью autoexpect
В целом, за исключением некоторых деталей, перед нами такой же скрипт, который мы писали самостоятельно. Если запустить этот скрипт, результат будет тем же.
Запуск expect-скрипта, созданного автоматически
При записи сеансов взаимодействия с некоторыми программами, вроде FTP-клиентов, вы можете столкнуться с тем, что они используют в выводимых данных сведения о времени проведения операции, или выводят данные, отражающие процесс выполнения неких продолжительных действий. В целом, речь идёт о том, что вывод программы при каждом её запуске, правильно воспринимаемый человеком и вызывающий ввод одних и тех же ответов, будет, в тех же условиях, выглядеть по-новому для expect.
Если в expect-скрипте строки, ожидаемые от такой программы, будут жёстко зафиксированы, такой скрипт не сможет нормально работать. Справиться с этим можно, либо удалив из expect-скрипта данные, которые выглядят по-новому при каждом запуске программы, либо использовав шаблоны, пользуясь которыми, expect сможет правильно понять то, что хочет от него программа.
Как видите, autoexpect — это весьма полезный инструмент, но и он не лишён недостатков, исправить которые можно только вручную. Поэтому продолжим осваивать язык expect-скриптов.
Работа с переменными и параметрами командной строки
Для того, чтобы получить доступ к аргументам командной строки, с которыми вызван expect-скрипт, можно поступить так:
Expect-скрипт, использующий переменные и параметры командной строки
Как видите, всё работает так, как ожидалось. Теперь expect-скрипт отвечает на вопросы bash-скрипта, пользуясь переданными ему параметрами командной строки.
Ответы на разные вопросы, которые могут появиться в одном и том же месте
Если автоматизируемая программа может, в одной ситуации, выдать одну строку, а в другой, в том же самом месте — другую, в expect можно использовать блоки, заключённые в фигурные скобки и содержащие варианты реакции скрипта на разные данные, полученные от программы. Выглядит это так:
Здесь, если expect-скрипт увидит строку «something», он отправит ответ «send this». Если же это будет некая строка, оканчивающаяся на «another», он отправит ответ «send another».
Тут мы генерируем случайное число при каждом запуске скрипта, и, проанализировав его, выводим один из двух вопросов.
Для автоматизации такого скрипта нам и пригодится вышеописанная конструкция:
Ответы на разные вопросы, появляющиеся в одном и том же месте
Как видно, когда автоматизированный скрипт выводит строку, оканчивающуюся на «topic?», expect-скрипт передаёт ему строку «Programming». Получив в том же месте, при другом запуске программы, вопрос, оканчивающийся на «movie?», expect-скрипт отвечает: «Star wars». Это очень полезная техника.
Условный оператор
Expect поддерживает условный оператор if-else и другие управляющие конструкции. Вот пример использования условного оператора:
Условный оператор в expect
Тут мы присваиваем переменной TOTAL некое число, после чего проверяем его и выводим текст, зависящий от результата проверки.
Обратите внимание на конфигурацию фигурных скобок. Очередная открывающая скобка должна быть расположена на той же строке, что и предыдущие конструкции.
Цикл while
Циклы while в expect очень похожи на те, что используются в обычных bash-скриптах, но, опять же, тут применяются фигурные скобки:
Цикл while в expect
Цикл for
Цикл for в expect устроен по-особому. В начале цикла, в самостоятельных парах фигурных скобок, надо указать переменную-счётчик, условие прекращения цикла и правило модификации счётчика. Затем, опять же в фигурных скобках, идёт тело цикла:
Объявление и использование функций
Expect позволяет программисту объявлять функции, используя ключевое слово proc :
Вот как выглядит expect-скрипт, в котором используется объявленная в нём же функция:
Команда interact
Когда выполняется эта команда, expect-скрипт переключается на чтение ответа на вопрос программы с клавиатуры, вместо того, чтобы передавать ей ранее записанные в нём данные.
Вот bash-скрипт, в общем-то, точно такой же, как мы рассматривали ранее, но теперь ожидающий ввод пароля в ответ на один из своих вопросов:
Напишем expect-скрипт, который, когда ему предлагают предоставить пароль, передаёт управление нам:
Команда interact в expect-скрипте
Итоги
Возможностями expect можно пользоваться в программах, написанных на разных языках программирования благодаря соответствующим библиотекам. Среди этих языков — C#, Java, Perl, Python, Ruby, и другие. То, что expect доступен для разных сред разработки — далеко не случайность. Всё дело в том, что это действительно важный и полезный инструмент, который используют для решения множества задач. Здесь и проверка качества ПО, и выполнение различных работ по сетевому администрированию, автоматизация передачи файлов, автоматическая установка обновлений и многое другое.
Освоив этот материал, вы ознакомились с основными концепциями expect и научились пользоваться инструментом autoexpect для автоматического формирования скриптов. Теперь вы вполне можете продолжить изучение expect, воспользовавшись дополнительными источниками. Вот — сборник учебных и справочных материалов. Вот — достойная внимания серия из трёх статей (1, 2, 3). А вот — официальная страница expect, на которой можно найти ссылки на исходный код программы и список публикаций.
На этом мы завершаем серию материалов о bash-скриптах. Надеемся, её одиннадцать частей, а также бессчётное число комментариев к ним, помогли в достижении цели тем, кто хотел научиться писать сценарии командной строки.
Уважаемые читатели! Благодарим всех, кто был с нами. Желаем удачной автоматизации работы в Linux! И, если у вас есть опыт работы с expect — ждём ваших рассказов.
Автоматизируем работу в интерактивных консольных программах используя expect
В жизни сетевого инженера (да и не только), наступает такой момент, когда некоторые рутинные операции надоедает выполнять, и хочется их оптимизировать. В один прекрасный день я понял, что каждый раз когда мне нужно авторизоваться на коммутаторе, то набирать логин\пароль, а затем ещё пароль на enable мне надоело. Поэтому данное действие было решено как-то оптимизировать. Взяв бутылочку пенного я сел за «работу»..
В компании где я работаю, по определённым обстоятельствам авторизация на коммутаторах\роутерах\DSLAM и прочем оборудовании происходит не по ssh, а по telnet. Средствами самого telnet возможности передать логин\пароль нет, поэтому поиск с попутным распитием алкоголя продолжился, и остановился на утилите expect.
Для моей задачи expect подошёл идеально. Да и как оказалось, у одного из коллег уже был небольшой expect скрипт для этих целей, который, правда, не совсем подходил мне, но для ознакомления с expect пришёлся весьма кстати.
Чтобы более или менее понять, рассмотрим для начала небольшой expect скрипт, который авторизует пользователя на ftp сервере:
Если что-то во время выполнения скрипта идёт не так, то можно посмотреть более подробно, какие данные получает expect, нашёл ли совпадения, и что посылает в ответ. Для этого надо добавить exp_internal 1 в код скрипта:
Видно, что после отправки пароля, ftp сервер снова его спрашивает. Значит, ошиблись где-то в логине или пароле.
Теперь пример сложнее. Скрипт выше делает то, что нам нужно в данном случае, но в нём есть некоторые недостатки: для каждого хоста необходимо создавать новый скрипт; если сайт недоступен, то скрипт будет вести себя весьма странно.
Исправим эти недостатки немного модифицировав его (для удобства добавленные\изменённые участки кода прокомментированы):
Раз уж мы заговорили про использование expect в bash, то коснёмся и сбора данных. Для примера давайте представим, что есть сферический ftp сервер в вакууме, с которого зачем-то нужно раз в сутки собирать список имеющихся директорий. Ситуация надуманная, но для примера подойдёт:
Пример принципиально не сильно отличается от предыдущего. В переменной DIRLIST запускаем expect и построчно выполняем скрипт. Следует обратить внимание, что так как мы запустили expect внутри bash, то надо дополнительно экранировать посылаемые и ожидаемые данные. Далее работаем с полученными результатами как с простым текстом.
Для моих нужд в результате получился такой скрипт: