вцуйф ауцй. Bash скрипты
Скачать 3.58 Mb.
|
Autoexpect — автоматизированное создание скриптов Autoexpect позволяет запускать программы, которые надо автоматизировать, после чего записывает то, что они выводят, и то, что пользователь вводит, отвечая на их вопросы. Вызовем autoexpect, передав этой утилите имя нашего скрипта $ autoexpect ./questions В этом режиме взаимодействие с скриптом ничем не отличается от обычного мысами вводим ответы на его вопросы. Запуск скрипта с помощью autoexpect После завершения работы с скриптом, autoexpect сообщит о том, что собранные данные записаны в файл script.exp. Взглянем на этот файл. 139 Файл script.exp В целом, за исключением некоторых деталей, перед нами такой же скрипт, который мы писали самостоятельно. Если запустить этот скрипт, результат будет тем же. Запуск скрипта, созданного автоматически При записи сеансов взаимодействия с некоторыми программами, вроде клиентов, вы можете столкнуться стем, что они используют в выводимых данных сведения о времени проведения операции, или выводят данные, отражающие процесс выполнения неких продолжительных действий. В целом, речь идёт о том, что вывод программы при каждом её запуске, правильно воспринимаемый человеком и вызывающий ввод одних и тех же ответов, будет, в тех же условиях, выглядеть по-новому для expect. Если в скрипте строки, ожидаемые от такой программы, будут жёстко зафиксированы, такой скрипт не сможет нормально работать. Справиться с этим можно, либо удалив из скрипта данные, которые выглядят по-новому при каждом запуске программы, либо использовав шаблоны, пользуясь которыми, expect сможет правильно понять то, что хочет от него программа. Как видите, autoexpect — это весьма полезный инструмент, но ион не лишён недостатков, исправить которые можно только вручную. Поэтому продолжим осваивать язык скриптов. Работа с переменными и параметрами командной строки Для объявления переменных в скриптах используется команда set. Например, для того, чтобы присвоить значение 5 переменной VAR1, используется следующая конструкция set VAR1 5 140 Для доступа к значению переменной переде именем надо добавить знак доллара — $. В нашем случае это будет выглядеть как $VAR1. Для того, чтобы получить доступ к аргументам командной строки, с которыми вызван скрипт, можно поступить так set VAR [lindex $argv 0] Тут мы объявляем переменную VAR и записываем вне указатель на первый аргумент командной строки, $argv 0. Для целей обновлённого скрипта мы собираемся записать значение первого аргумента, представляющее собой имя пользователя, которое будет использовано в программе, в переменную my_name. Второй аргумент, символизирующий то, что пользователю нравится, попадёт в переменную my_favorite. В результате объявление переменных будет выглядеть так set my_name [lindex $argv 0] set my_favorite [lindex $argv 1] Отредактируем скрипт answerbot, приведя его к такому виду #!/usr/bin/expect -f set my_name [lindex $argv 0] set my_favorite [lindex $argv 1] set timeout -1 spawn ./questions expect "Hello, who are you?\r" send -- "Im $my_name\r" expect "Can I ask you some questions?\r" send -- "Sure\r" expect "What is your favorite topic?\r" send -- "$my_favorite\r" expect eof Запустим его, передав в качестве первого параметра SomeName, в качестве второго — Programming: $ ./answerbot SomeName Programming 141 скрипт, использующий переменные и параметры командной строки Как видите, всё работает так, как ожидалось. Теперь скрипт отвечает на вопросы скрипта, пользуясь переданными ему параметрами командной строки. Ответы на разные вопросы, которые могут появиться водном и том же месте Если автоматизируемая программа может, водной ситуации, выдать одну строку, а в другой, в том же самом месте — другую, в expect можно использовать блоки, заключённые в фигурные скобки и содержащие варианты реакции скрипта на разные данные, полученные от программы. Выглядит это так expect { "something" { send -- "send this\r" } "*another" { send -- "send another\r" } } Здесь, если скрипт увидит строку «something», он отправит ответ «send this». Если же это будет некая строка, оканчивающаяся на «another», он отправит ответ «send another». Напишем новый скрипт, записав его в файл questions, случайным образом задающий водном и том же месте разные вопросы #!/bin/bash let number=$RANDOM if [ $number -gt 25000 ] then echo "What is your favorite topic?" else echo "What is your favorite movie?" fi read $REPLY Тут мы генерируем случайное число при каждом запуске скрипта, и, проанализировав его, выводим один из двух вопросов. Для автоматизации такого скрипта нами пригодится вышеописанная конструкция #!/usr/bin/expect -f set timeout -1 spawn ./questions expect { "*topic?" { send -- "Programming\r" } 142 "*movie?" { send -- "Star wars\r" } } Ответы на разные вопросы, появляющиеся водном и том же месте Как видно, когда автоматизированный скрипт выводит строку, оканчивающуюся на «topic?», expect- скрипт передаёт ему строку «Programming». Получив в том же месте, при другом запуске программы, вопрос, оканчивающийся на «movie?», скрипт отвечает «Star wars». Это очень полезная техника. Условный оператор Expect поддерживает условный оператор if-else и другие управляющие конструкции. Вот пример использования условного оператора #!/usr/bin/expect -f set TOTAL 1 if { $TOTAL < 5 } { puts "\nTOTAL is less than 5\n" } elseif { $TOTAL > 5 } { puts "\nTOTAL greater than 5\n" } else { puts "\nTOTAL is equal to 5\n" } expect eof Условный оператор в expect Тут мы присваиваем переменной TOTAL некое число, после чего проверяем его и выводим текст, зависящий от результата проверки. 143 Обратите внимание на конфигурацию фигурных скобок. Очередная открывающая скобка должна быть расположена на той же строке, что и предыдущие конструкции. Цикл while Циклы while в expect очень похожи нате, что используются в обычных скриптах, но, опять же, тут применяются фигурные скобки #!/usr/bin/expect -f set COUNT 0 while { $COUNT <= 5 } { puts "\nCOUNT is currently at $COUNT" set COUNT [ expr $COUNT + 1 ] } puts "" Цикл while в expect Цикл for Цикл for в expect устроен по-особому. Вначале цикла, в самостоятельных парах фигурных скобок, надо указать переменную-счётчик, условие прекращения цикла и правило модификации счётчика. Затем, опять же в фигурных скобках, идёт тело цикла #!/usr/bin/expect -f for {set COUNT 0} {$COUNT <= 5} {incr COUNT} { puts "\nCOUNT is at $COUNT" } puts "" 144 Цикл for в expect Объявление и использование функций Expect позволяет программисту объявлять функции, используя ключевое слово proc: proc myfunc { MY_COUNT } { set MY_COUNT [expr $MY_COUNT + 1] return "$MY_COUNT" } Вот как выглядит скрипт, в котором используется объявленная в нём же функция #!/usr/bin/expect -f proc myfunc { MY_COUNT } { set MY_COUNT [expr $MY_COUNT + 1] return "$MY_COUNT" } set COUNT 0 while {$COUNT <= 5} { puts "\nCOUNT is currently at $COUNT" set COUNT [myfunc $COUNT] } 145 puts "" Функции в expect Команда interact Случается так, что автоматизируемые с помощью expect программы требуют ввода конфиденциальных данных, вроде паролей, которые вам не хотелось бы хранить в виде обычного текста в коде скрипта. В подобной ситуации можно воспользоваться командой interact, которая позволит вам, автоматизировав некую часть взаимодействия с программой, самостоятельно ввести, скажем, пароль, а потом опять передать управление expect. Когда выполняется эта команда, скрипт переключается на чтение ответа на вопрос программы с клавиатуры, вместо того, чтобы передавать ей ранее записанные в нём данные. Вот скрипт, в общем-то, точно такой же, как мы рассматривали ранее, но теперь ожидающий ввод пароля в ответ на один из своих вопросов #!/bin/bash echo "Hello, who are you?" read $REPLY echo "What is you password?" read $REPLY echo "What is your favorite topic?" read $REPLY Напишем скрипт, который, когда ему предлагают предоставить пароль, передаёт управление нам 146 #!/usr/bin/expect -f set timeout -1 spawn ./questions expect "Hello, who are you?\r" send -- "Hi Im Adam\r" expect "*password?\r" interact ++ return send "\r" expect "*topic?\r" send -- "Technology\r" expect Команда interact в скрипте Встретив команду interact, скрипт остановится, предоставив нам возможность ввести пароль. После ввода пароля надо ввести «++» и скрипт продолжит работу, снова получив управление. Итоги Возможностями expect можно пользоваться в программах, написанных на разных языках программирования благодаря соответствующим библиотекам. Среди этих языков — C#, Java, Perl, Python, Ruby, и другие. То, что expect доступен для разных сред разработки — далеко неслучайность. Всё дело в том, что это действительно важный и полезный инструмент, который используют для решения множества задач. Здесь и проверка качества ПО, и выполнение различных работ по сетевому администрированию, автоматизация передачи файлов, автоматическая установка обновлений и многое другое. Освоив этот материал, вы ознакомились с основными концепциями expect и научились пользоваться инструментом autoexpect для автоматического формирования скриптов. Теперь вы вполне можете продолжить изучение expect, воспользовавшись дополнительными источниками. Вот — сборник учебных и справочных материалов. Вот — достойная внимания серия из трёх статей ( 1 , 2 , 3 ). А вот — официальная страница expect, на которой можно найти ссылки на исходный код программы и список публикаций. На этом мы завершаем серию материалов о скриптах. Надеемся, её одиннадцать частей, а также бессчётное число комментариев к ним, помогли в достижении цели тем, кто хотел научиться писать сценарии командной строки. |