Expect(1)

Материал из wiki.lissyara.su
Перейти к: навигация, поиск

НАЗВАНИЕ

expect - программируемый диалог для интерактивных программ, Версия 5

СИНТАКСИС

expect [ -dDinN ] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

ВВЕДЕНИЕ

Expect это программа которая "разговаривает" с другими интерактивными программами в соответствии со сценарием. Следуя сценарию, Expect знает что ожидать от программы и что ответить программе. Интерпретируемый язык обеспечивает расширенный и высокоуровневый контроль механизмов направления диалога. В дополнение, пользователь может взять управление в свои руки и работать с программой по своему усмотрению, возвращая впоследствии управление сценарию.
Expectk - это смесь из Expect и Tk. Он ведёт себя подобно Expect'у и Tk. Expect может быть использован непосредственно в C или C++ (то есть, без Tcl). Смотрите libexpect(3).
Название "Expect" взято с идеи отправки/приёма последовательностей, подобно uucp, kermit и других программ управления модемом. Тем не менее в отличие от uucp, Expect запускается как пользовательская команда для работы с любыми другими программами и задачами. Expect может работать одновременно с несколькими программами.
Например, вот некоторые функции которые может выполнять Expect:
  • Компьютер может перезванивать Вам, и Вы можете залогиниться без оплаты исходящего звонка.
  • Запустить игру (например, rogue) и перезапускать её (снова и снова) пока не будет достигнута оптимальная конфигурация, затем можно взять контроль в свои руки.
  • Запустить fsck, и отвечать "да" или "нет" на его вопросы, или взять управление на себя, в зависимости от определённых условий.
  • Подключиться к другой сети или BBS (например, MCI Mail, CompuServe) и автоматически получать письма.
  • Переносить переменные среды, текущую директорию или другую информацию через rlogin, telnet, tip, su, chgrp и т.д.
Оболочка не может выполнять эти задачи по различным причинам. (Попробуйте, и Вы поймёте.) Всё это возможно с помощью Expect'а.
В целом, Expect используется для работы с программами требующими участия пользователя. Всё это необходимо для программирования интерактивности. При необходимости Expect также может предоставить контроль непосредственно пользователю (без приостановления программы). Аналогично, пользователь может вернуть управление сценарию в любое время.

ИСПОЛЬЗОВАНИЕ

Expect читает и исполняет команды из файла. Expect может быть также вызван на системах поддерживающих нотацию #!, используемую для метки исполняемого сценария, в этом случае, первая строка в вашем сценарии должна быть такой:
#!/usr/local/bin/expect -f
Конечно, путь должен указывать на расположение Expect'а. В данном случае, /usr/local/bin просто пример.
Флаг -c предисловие к команде которая должна исполняться перед сценарием. Команда должна заключаться в кавычки, иначе она может быть нарушена сценарием. Эта опция может быть использована многократно. Многочисленные команды могут запускаться с помощью единственного флага -c и должны быть разделены точкой с запятой. Команды исполняются в порядке их следования. (При использовании Expectk, эта опция определяется как -command.)
Флаг -d включает диагностический вывод, который отображает внутреннюю активность таких команд как expect и interact. Этот флаг почти аналогичен "exp_internal 1" и запускает сценарий Expect'а, плюс выводит версию Expect'а. (Команда strace полезна для трассировки операторов, команд и переменных.) (При использовании Expectk, эта опция обозначается как -diag.)
Флаг -D включает интерактивный отладчик. Должно следовать целочисленное значение. Отладчик берёт контроль перед следующей Tcl процедурой если значение не ноль или нажата ^C (или нажата точка останова, или в сценарии есть команда передачи управления другому отладчику). Читайте README файл или ЧИТАЙТЕ ТАКЖЕ (ниже) для подробной информации об отладчике. (При использовании Expectk, эта опция обозначается как -Debug.)
Флаг -f обозначает файл из которого будут читаться команды на исполнение. Флаг опционален только при использовании нотации #! (смотрите выше), другие аргументы могут быть применены в коммандной строке. (При использовании Expectk, эта опция обозначается как -file.)
По умолчанию, командный файл читается в память и исполняется оттуда. Только изредка может понадобиться построчное чтение и исполнение команд из файла. Например, stdin использует этот метод. Для использования этого пути, используйте флаг -b. (При использовании Expectk, эта опция определяется как -buffer.)Помните,могутвозникнутьпроблемыпричтенииданныхизstdin.
Если строка "-" является именем файла, то будет читаться данные из стандартного входа. (Используйте "./-" для чтения из файла названного "-".)
Флаг -i заставляет Expect выдавать подтверждение для команд читаемых из файла. Подтверждение заканчивается с помощью команды exit или достижении EOF. Смотрите интерпретатор (ниже) за более подробной информацией. -i предполагается при отсутствии использования командного файла и флага -c. (При использовании Expectk, эта опция определяется как -interactive.)
-- может быть использовано в качестве разграничителя конца опции. Это полезно если Вам нужно передать аргумент похожий на опцию без интерпретации его Expect'ом. Также, полезно поместить его в строку с #! для предотвращения любых флагоподобных интерпретаций Expect'ом. Следующий пример показывает как оставить оригинальные аргументы (включая имя сценария) в значениях.
#!/usr/local/bin/expect --
Помните, обычные getopt(3) и execve(2) соглашения должны соблюдаться при добавлении аргументов в строку с #!.
Файл $exp_library/expect.rc автоматически создаётся, если используется флаг -N. (При использовании Expectk, эта опция определяется как -NORC.) Сразу после этого, файл ~/.expect.rc автоматически создаётся, если используется флаг -n. Если переменная окружения DOTDIR определена, то чтение происходит из директории и .expect.rc. (При использовании, эта опция определяется как -norc.) Это обращение происходит после исполнения любого -c флага.
-v заставляет Expect печатать его версию и выходит из Expect'а. (Соответствующий флаг в Expectk, который использует длинные имена файлов, это -version.)
Опциональные аргументы составлены в список и сохранены в значениях названными как argv. argc содержит длину argv.
argv0 содержит название скрипта (или бинарника если используется не скрипт). Следующий пример печатает название сценария и первые три аргумента.:
send_user "$argv0 [lrange $argv 0 2]\n"


КОМАНДЫ

Expect использует Tcl (Tool Command Language). Tcl обеспечивает управление программой (т.е., if, for, break), вычисление выражений и другие особенности, такие как, рекурсия, объявление процедур и т.д. Команды используемые здесь, но не объявленные (такие как: set, if, exec) являются командами Tcl (смотрите tcl(3)). Expect поддерживает дополнительные команды, описанные ниже. Описанные в другом случае, команды возвращают пустую строку.
Команды предоставлены в алфавитном порядке, таким образом, они могут быть быстро найдены. Однако, новички могут начать работать с Expect прочитав описание в следующем порядке: spawn, send, expect и interact.
Помните что лучшее введение в язык (Expect и Tcl) предоставлено в книге "Изучение Expect" (смотрите ЧИТАЙТЕ ТАКЖЕ ниже). Примеры, включенные в эту man страницу, очень ограничены, поскольку man, в первую очередь, справочный материал.
Помните, что текст в этом man'е, "Expect" с верхним регистром "E" означает программу Expect, в то время как, нижний разрядный "e" означает команду expect без программы Expect.
close [-slave] [-onexec 0|1] [-i spawn_id]
закрывает подключение к текущему процессу. Большинство интерактивных программ определяют EOF в их stdin и exit; таким образом close обычно достаточно для завершения процесса. Флаг -i помечает процесс для закрытия с соответствующим spawn_id.
Обе команды, expect и interact определяют когда текущий процесс завершился и подразумевается выполнение закрытия. Но, если Вы завершили процесс, к примеру, "exec kill $pid", Вам придётся явно вызывать close.
Флаг -onexec определяет закрытие порождённого id в других порождённых процессах или если процесс перекрыт. Для того, чтобы оставить порождённый id открытым, используйте значение 0. Не нулевое целое значение принудительно завершит в других новых процессах (по умолчанию).
Флаг -slave закрывает порождённый id ассоциированный со slave'ом. (Смотрите "spawn -pty".) При закрытии соединения, slave автоматически закрывается, даже если он был открыт.
Не зависимо от явного или подразумеваемого закрытия соединения, Вам следует вызывать wait для очистки соответствующего процессорного слота ядра. close не вызывает wait поскольку нет гарантий закрытия соединения процесса вызвавшего exit. Для получения дополнительной информации, смотрите wait ниже.
debug [[-now] 0|1]
контролирование отладчика Tcl позволяет просматривать значения, устанавливать точки останова и т.д.
Без аргументов, возвращается 1, если отладчик запущен, в другом случае возвращается 0.
С 1 в качестве аргумента, запускается отладчик. С 0 в качестве аргумента, отладчик останавливается. Если перед аргументом 1, предшествует флаг -now, отладчик запускается незамедлительно (т.е., непосредственно в середине команды debug). В противном случае отладчик запускается со следующего Tcl команды.
Команда debug ничего не меняет. Сравните её с запуском Expect с флагом -D (смотрите выше).
Смотрите README файл и ЧИТАЙТЕ ТАКЖЕ (ниже) для более полной информации об отладчике.
disconnect
отключается от форкнутого процесса с терминала. Он продолжает работать на заднем фоне. Процесс получает собственную процессную группу (если это возможно). Стандартный Ввод/Вывод перенаправляется в /dev/null.
Следующий фрагмент использует disconnect для продолжения работы сценария в фоновом режиме.

if {[fork]!=0} exit
disconnect
. . .

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

send_user "password?\ "
expect_user -re "(.*)\n"
for {} 1 {} {
    if {[fork]!=0} {sleep 3600;continue}
    disconnect
    spawn priv_prog
    expect Password:
    send "$expect_out(1,string)\r"
    . . .
    exit
}

Преимущество использования disconnect'а над шелловским свойством асинхронного процесса (&), в том, что Expect может сохранить, предшествующие отключению, параметры терминала, и затем позже применить их к следующему pty. C & Expect не имеет возможности считать параметры терминала, отключенного с помощью контроля Expect.
exit [-opts] [status]
вынуждает Expect завершить работу или в противном случае подготавливает Expect к завершению работы.
Флаг -onexit заставляет использовать следующий аргумент в качестве хендлера выхода. Без аргумента, в качестве выхода, возвращается текущий хендлер.
Флаг -noexit принуждает Expect подготовиться к завершению работы и возвращает контроль операционной системе. Обозначенный пользователем хендлер выхода используется как внутренний хендлер Expect'а. Никакие другие команды Expect'а исполняться не будут. Полезно в случае запуска Expect'а с другими расширениями Tcl. Текущий интерпретатор (и главное окно в окружении Tk) остаётся, остальные расширения Tcl могут очиститься. Если команда Expect'а вызвана снова (такое бывает), хендлеры не возвращаются.
При выходе, все соединения с порождёнными процессами закрываются. Порождёнными процессами закрытие не определяется как EOF. exit не производит никаких других действий кроме обычной процедуры _exit(2). Таким образом, порождённые процессы, не проверяющие EOF, могут оставаться запущенными. (Некоторые условия требуют пристального внимания, на пример, сигнал посылаемый порождённому процессу, но это зависит от операционной системы, задокументировано под exit(3).) Порождённый процесс, продолжающий работать, наследуется init'ом.
status (или 0 если не определён) возвращается в качестве статуса завершения работы Expect'а. exit подразумевается при достижении конца сценария.
exp_continue [-continue_timer]
Команда exp_continue заставляет ожидать себя для продолжения исполнения. По умолчанию exp_continue сбрасывает таймер таймаута. Флаг -continue_timer не разрешает перезапуск таймера. (Смотрите expect для подробной информации.)
exp_internal [-f file] значение
включает отправку диагностической информации на stderr от команд Expect'а в случае не нулевого значения. Вывод отладочной информации отключается установкой значения в 0. Диагностическая информация включает каждый полученный символ, и каждую попытку сравнения текущего вывода против заданного образца.
Если опциональный файл существует, все нормальные и отладочные сообщения будут записываться в него (независимо от значения). Другой предыдущий файл будет закрыт.
Флаг -info включает возврат дескриптора не информативных аргументов.
exp_open [args] [-i spawn_id]
возвращает идентификатор Tcl файла, содержащего оригинальный спаун id. Идентификатор файла может быть использован командой open языка Tcl. (Спаун id больше не используется.) wait более не исполняется.
Флаг -leaveopen оставляет открытым спаун id для доступа через команды Expect'а. wait может быть исполнен через спаун id.
exp_pid [-i spawn_id]
возвращает id процесса соответствующему порождённому процессу. При использовании флага -i возвращается pid соответствующий заданному spawn_id.
exp_send
алиас для send.
exp_send_error
алиас для send_error.
exp_send_log
алиас для send_log.
exp_send_tty
алиас для send_tty.
exp_send_user
алиас для send_user.
exp_version [[-exit] version]
полезно для выяснения совместимости сценария с текущей версией Expect'а.
Без аргументов, возвращается текущая верся Expect'а. Эта версия может быть добавлена в Ваш сценарий. Если Вы точно знаете, что не используете особенности недавних версий, Вы можете определить раннюю версию.
Версии содержат три номера разделённых точками. Первый - мажорный номер. Сценарии написанные для версий Expect'а с различными мажорными номерами, чаще всего, не работают. exp_version вернёт ошибку несоответствия мажорных номеров.
Второй - минорный номер. Сценарий написанный для версии с большим минорным номером, чем текущий, может зависеть от некоторых новых особенностей и, вероятно, не будет работать. exp_version возвращает ошибку если мажорный номер соотвествует, но минорный номер сценария больше чем минорный номер запущенного Expect'а.
Третий номер не играет роли в версионном сравнении. Тем не менее, он увеличивается на единицу при изменении программного обеспечения Expect, например, дополнительная документация или оптимизация. Этот номер устанавливается в 0 при каждой новой минорной версии.
При флаге -exit, Expect печатает ошибку и завершает работу, если версия устарела.
expect [[-opts] pat1 body1] ... [-opts] patn [bodyn]
ожидает пока один из образцов (pat) не будет соответствовать выводу порождённого процесса, или пока не истечёт определённый период времени, или достигнут конец-файла. Если тело (body) пусто, то команда может быть пропущена.
Образцы от недавней команды expect_before приоритетнее чем другие образцы. Образцы от недавней команды expect_after менее приоритетнее чем другие образцы.
Если аргументы внутри выражения expect не помещаются в одну линию,то, все аргументы могут быть скреплены в один с помощью бэкслеша. В этом случае происходит подстановка Tcl несмотря на скобки.
Если образец является ключевым словом eof, соответствующее тело исполняется на конец-файла (end-of-file). Если образец является ключевым словом timeout, соответствующее тело исполняется на таймаут. Если использовано ключевое слово являющееся не таймаутом, то подразумевается бездействие на таймаут. По умолчанию, период таймаута установлен в 10 секунд, но также можноустановить, к примеру, в 30, командой "set timeout 30". На бесконечный таймаут определено значение -1. Если образец является ключевым словом default, то соответствующее тело исполняется накаждый таймаут или конец-файла (end-of-file).
Если обнаруживается совпадение с образцом, то исполняетсясоответствующее тело. expect возвращает результат тела (или пустую строку если не обнаружено совпадений с образцом). В случае множественного совпадения с образцами, исполняется первое тело.
Каждый получаемый вывод, сравнивается с каждым образцом в том порядке в котором они перечислены. Таким образом, Вы можете испытать на отсутствие совпадений поставив последним образцом что-нибудь гарантированно появляющееся, например: приглашение (prompt). В случае отсутствия приглашения, Вы можете использовать timeout.
Образцы определяются тремя путями. По умолчанию, образцы определены командой совпадения строк языка Tcl. (Такие образцы подобны регулярным выражениям C-shell'а, например: образцы "glob"). Флаг -gl используется для защиты образцов могущих соответствовать флагам expect'а. Все образцы начинаются с "-" должны быть защищены подобным образом. (Все строки начинающиеся с "-" зарезервированы для будущего использования.)


Для примера, следующий фрагмент проверяет удачную регистрацию в системе. (Помните, что abort является предполагаемой процедурой обозначенной во всём скрипте.)

expect {
    busy		{puts busy\n ; exp_continue}
    failed		abort
    "invalid password"	abort
    timeout		abort
    connected
}

Кавычки необходимы на четвёртом образце поскольку он содержит пробел, который должен разделять образец от действия. Даже если встречаются образцы с одинаковыми действиями (такие как 3-ий и 4-ый) их всё равно требуется вводить снова. Этого можно избежатьиспользуя образцы в стиле регулярных выражений (смотрите ниже).Больше информации о формировании glob подобных образцов Вы можетенайти в руководстве к Tcl.
Образцы в стиле регулярных выражений следуют синтаксису обозначенному в команде regexp (сокращение от "регулярные выражения") языка Tcl. Образцы regexp вводятся с флагом -re. Предыдущий пример может быть переписан следующим образом:

expect {
    busy	{puts busy\n ; exp_continue}
    -re "failed|invalid password" abort
    timeout	abort
    connected
}

Оба типа образцов являются "не фиксированными". Это означает что образец не совпадает в целой строке, но может встретиться в любом месте строки (по всей длине). Используйте ^ для обозначения начала строки, и $ для обозначения конца. Помните, что если Вы не будете ждать конца строки, Ваш ответ может придти к середине строки и может быть возвращён порождённым процессом. Для получения корректных результатов, такой вывод может выглядеть не ествественно. Таким образом, использование $ поддерживается если Вы можете точно описать символы конца строки.
Помните, что во многих редакторах символы ^ и $ соответствуют началу и концу строки. Но, так как expect не ориентирован настроки, эти символы обозначают начало и конец данных(противопоставляя их линиям) находящихся в данный момент в буфере expect'а. (Также, смотрите примечания ниже о "невосприятиисистемы")
Флаг -ex включает соответствие образца со строкой "exact". Не производится интерпретация с символами *, ^, и т.д. (хотя обычные Tcl соглашения остаются в силе). Точные образцы всегда не фиксированы.


Флаг -nocase отключает чувствительность к регистру. При этом образец не изменяется.
При чтении вывода, запоминается не более чем 2000 последних байтов, остальные "забываются". Эту переменную можно изменить функцией match_max. (Помните что чрезмерно большой объём запоминаемых байтов может затормозить сравнение образцов.) Если буфер заполнится, соответствующее тело запустится при условии,что получены match_max байты и все остальные образцы несовпадают. Независимо от использования ключевого слова full_buffer, забытые символы будут записаны в expect_out (буфер).
Если в списке образцов есть ключевое слово null, и допускается null (с командой remove_nulls), соответствующее тело исполнитсяпри совпадении единственного ASCII 0. Невозможно сравнить 0 байтов через glob или regexp'ы.
Со сравнением образцов (или eof или full_buffer), другие сравнения и предыдущий несовпадающий вывод сохраняется в переменную expect_out (буфер). До 9 совпадений regexp'ов записываются в переменные c expect_out(1,string) до expect_out(9,string). Если перед образцом использован флаг -indices, начальный и конечный индекс (в форме используемой lrange'ем) до 10 строк сохраняется в переменные expect_out(X,start) и expect_out(X,end), где X цифра, соответствующая позиции подстроки в буфере. 0 отмечает строки которые соответствуют целому образцу и создаётся для glob образцов, а также regexp образцов. На пример, если процесс выдаёт вывод в виде "abcdefgh\n", то результат:

expect "cd"

будет следующим:

set expect_out(0,string) cd
set expect_out(buffer) abcd

и "efgh\n" останется слева в буфере вывода. Если процесс выдал вывод "abbbcabkkkka\n", результат:

expect -indices -re "b(b*).*(k+)"

будет следующим:

set expect_out(0,start) 1
set expect_out(0,end) 10
set expect_out(0,string) bbbcabkkkk
set expect_out(1,start) 2
set expect_out(1,end) 3
set expect_out(1,string) bb
set expect_out(2,start) 10
set expect_out(2,end) 10
set expect_out(2,string) k
set expect_out(buffer) abbbcabkkkk

и "a\n" будет слева в буфере вывода. Образец "*" (и -re ".*") сбросят вывод буфера без чтения другого вывода от других процессов.
Обычно, совпадающий вывод сбрасывается с внутреннего буфера Expect'а. Чтобы предотвратить такое поведение используйте флаг -notransfer. Этот флаг особенно полезен при экспериментировании (можно сокращать до "-not" для удобства во время экспериментирования).
Порождённый id ассоциируется с совпадающим выводом (или eof или full_buffer) сохраняемым в expect_out(spawn_id).
Флаг -timeout позволяет задать таймаут взамен переменной timeout.
По умолчанию, образцы сравниваются с выводом текущего процесса, однако, флаг -i позволяет сравнивать образцы с именованным spawn_id списком (вплоть до следующего -i). Список spawn_id должен разделяться пробелами, также пробелами должны разделяться переменные относящиеся к списку spawn_id.
Например, следующий код ожидает либо "connected" с текущим процессом, либо "busy", "failed" или "invalid password" от spawn_id именованного как $proc2.

expect {
    -i $proc2 busy {puts busy\n ; exp_continue}
    -re "failed|invalid password" abort
    timeout abort
    connected
}

Величина глобальной переменной any_spawn_id может использоваться для сравнения образцов с другими именованными spawn_id, с помощью флага -i в текущей команде expect. spawn_id с флагом -i без соответствующих образцов (то есть, следующий сразу за другим -i) делает доступным другие образцы в этой же команде expect асоциированной с другим spawn_id.
Флаг -i может именовать глобальную переменную, в этом случае переменная читается из списка порождённых id. Переменная перечитывается при каждом изменении. Так обеспечивается измение источника ввода/вывода во время исполнении команды. Этот путь называется "косвенными" порождёнными id.
Такие действия как break и continue управляют контролем структур(то есть, for, proc) и ведёт себя обычным образом. Команда exp_continue допускает продолжение исполнения команды expect.
Полезно для избегания явных повторов или повторяемых выражений. Следующий пример, является частью кода автоматизации rlogin'а. exp_continue позволяет избежать написания второй формулировки команды expect (для просмотра второго приглашения) если rlogin требует ввода пароля.
expect {
    Password: {
	 stty -echo
	 send_user "password (for $user) on $host: "
	 expect_user -re "(.*)\n"
	 send_user "\n"
	 send "$expect_out(1,string)\r"
	 stty echo
	 exp_continue
    } incorrect {
	 send_user "invalid password or account\n"
	 exit
    } timeout {
	 send_user "connection to $host timed out\n"
	 exit
    } eof {
	 send_user \
		"connection to host failed: $expect_out(buffer)"
	 exit
    } -re $prompt
}
На пример, следующий фрагмент поможет пользователю изучить интерактивность, поскольку полностью автоматизирован. В этом случае терминал устанавливается в raw режим. Если пользователь нажмёт "+", переменная увеличится на единицу. Если нажмёт "p", то несколько нажатий Enter'а будут отправлены процессу и "i" позволит пользователю взаимодействовать с процессом, эффективно перехватывая управление у сценария. В каждом случае, exp_continue позволяет expect'у продолжить сравнение после выполнения текущего действия.
stty raw -echo
expect_after {
    -i $user_spawn_id
    "p" {send "\r\r\r"; exp_continue}
    "+" {incr foo; exp_continue}
    "i" {interact; exp_continue}
    "quit" exit
}


По умолчанию, exp_continue сбрасывает счётчик таймаута. Таймер не перезапускается, если exp_continue вызывается с флагом -continue_timer.
expect_after [expect_args]
работает аналогично expect_before ожидает что образцы от expect'а и expect_after могут соответствовать, используется образец expect'а. Смотрите команду expect_before для более детальной информации.
expect_background [expect_args]
получает те же аргументы что и expect, однако возвращает их немедленно. Образцы проверяются при каждом новом вводе. Таймаут образцов и умолчания для expect_background не употребляются. В противном случае команда expect_background использует образцы expect_before и expect_after, как это делает expect.
Во время работы expect_background, работа других порождённых id блокируется. Фоновые процессы разблокируются при завершении всех действий. Во время блокировки фонового процесса, возможно исполнение (переднеплановых) expect'а в этом же порождённом id.
Невозможно исполнить expect при неблокированном expect_background'е. expect_background для конкретных порождённых id удаляется объявлением нового expect_background в том же порождённом id. Объявление expect_background без образцов лишает возможности проводить сравнения в фоновом режиме данному порождённому id.
expect_before [expect_args]
принимает такие же аргументы, что и expect, однако возвращает их немедленно. Пара образец-действие от последней команды expect_before с таким же порождённым id добавляется к следующим командам expect. Если образец совпадает, он обрабатывается внутри команды expect, и ассоциированное тело исполняется в контексте команды expect. Если встретятся совпадающие образцы между командами expect_before и expect, то будет использован образец expect_before.
Если никакие образцы не определены, порождённый id непроверяется на образцы.
В случае аннулирования флагом -i, образцы команды expect_before сравниваются с объявленным порождённым id во время исполнения команды expect_before (а не во время совпадения образца).
Флаг -info заставляет команду expect_before возвращать текущее определение совпавших образцов. По умолчанию, отчёт поступает в текущий порождённый id. Можно выдавать информацию с одного порождённого id на любой другой id. На пример:
expect_before -info -i $proc
Можно выдавать больше одного порождённого id. Флаг -indirect запрещает прямое порождение id, разрешая только косвенное объявление id.
Взамен спецификации порождённого id, флагом "-all" можно заставить "-info" выдавать отчёт на все порождённые id.
Вывод флага -info может быть использован в качестве аргумента для expect_before.
expect_tty [expect_args]
подобно expect'у, но читает символы из /dev/tty (то есть, строки печатаемые пользователем). По умолчанию, чтение выполняется в режиме подготовки. Таким образом, строки должны завершаться возвратом каретки, для того чтобы expect их увидел. Это можно изменить с помощью stty (смотрите команду stty ниже).
expect_user [expect_args]
подобно expect'у, но читает символы из stdin (то есть, строки печатаемые пользователем). По умолчанию, чтение выполняется врежиме подготовки. Таким образом, строки должны завершаться возвратом каретки, для того чтобы expect их увидел. Это можно изменить с помощью stty (смотрите команду stty ниже).
fork создаёт новый процесс.
Новый процесс - точная копия текущего процесса Expect. При удачной попытке, форк возвращает 0 в новый(форкнутый) процесс и возвращает id порождённого процесса в родительский процесс. При неудаче (в результате недостатка ресурсов, то есть, свопа, памяти и т.д.), форк возвращает -1 родительскому процессу, и порождённый процесс не создаётся.
Форкнутый процесс завершается через команду exit, так же, как иисходный процесс. Форкнутые процессы могут писать в лог файлы.Если Вы не отключили отладку или ведение логов в процессах, то это может привести к неразберихе.
Некоторые реализации pty могут создать путаницу многочисленными чтениями и записями в одно и то же время. Таким образом, лучше создать форк перед порождением процесса.
interact [string1 body1] ... [stringn [bodyn]]
передаёт контроль текущего процесса пользователю, набранные на клавиатуре строки отправляются текущему процессу, также возвращается контроль над stdout и stderr процесса.
Пара строка-тело может быть определено как аргумент, в этом случае тело исполняется в случае ввода соответствующей строки. (По умолчанию, строка не отправляется текущему процессу.) При отсутствии конечного тела, принимается команда интерпретатора.
Если аргументы для взаимодействующего оператора требуют ввода более чем одной строки, все аргументы могут быть взяты в "скобки", это более читабельно, чем окончание каждой строки бэкслэшем. В этом случае, обычные Tcl подстановки будут исполняться несмотря на скобки.
На пример, следующая команда запустит interact со следующей парой строка-тело: При нажатии ^Z Expect приостановится. (Флаг -reset восстановит режим терминала.) При нажатии ^A, пользователю будет выдано "you typed a control-A" и процесс отправит ^A. При нажатии $, будет выдана дата. При нажатии ^C, завершится работа Expect'а. Если введено "foo", пользователю будет выдано "bar". При нажатии ~~ интерпретатор Expect запустится в интерактивном режиме.
set CTRLZ \032
interact {
    -reset $CTRLZ {exec kill -STOP [pid]}
    \001   {send_user "you typed a control-A\n";
            send "\001"
           }
    $	    {send_user "The date is [exec date]."}
    \003   exit
    foo    {send_user "bar"}
    ~~
}


В паре строка-тело, строки сравниваются в том порядке, в котором они перечислены в аргументах. Частично соответствующие строки не отправляются текущему процессу, а находятся в ожидании поступления недостающей части строки. Если введённые символы несоответствуют, процессу будет послана только та часть строки,которая не может соответствовать другому образцу. Таким образом,строки, часть которых частично соответствует образцу, могут сравниваться позже, если оригинальные строки, которые не прошли через процедуру сравнения отбрасываются.
По умолчанию, строки сравниваются с игнорированием спец символов.(В противоположность команде expect использующей, по умолчанию, образцы в glob стиле.) Флаг -ex используется для защиты образцов, которые могут быть восприняты как флаги. Все образцы начинающиеся с "-" защищаются подобным способом. (Все строки, начинающиеся с "-", зарезервированы для будущего использования.)
Флаг -re указывает на интерпретацию образца, как регулярного образца. В этом случае, сравнение подстрок сохраняется в переменной interact_out, подобно команде expect, сохраняющей свой вывод в переменной expect_out. Флаг -indices работает так же, как и в команде expect.
Образец eof работает как end-of-file. Разделение образца eof может также следовать флагу -output, в таком случае сравнивается на eof при записи вывода. По умолчанию eof действует как "return".
Таймаут образца является таймаутом (в секундах) и действием, производимым при не получении символов в заданное время. Образец таймаута применяется к самому последнему процессу. Таймаут не имеет значения по умолчанию. Специальная переменная "timeout" (используется командой expect) не влияет на данный таймаут.
На пример, следующая конструкция используется для автологаута пользователя, который в течении часа ничего не напечатал, но часто получает системные сообщения:
interact -input $user_spawn_id timeout 3600 return -output \
    $spawn_id


Если образец является ключевым словом null, и null'и принимаются (через команду remove_nulls), то, соответствующее тело исполняется при совпадении единственного ASCII 0. Невозможно сравнивать 0 байтов через образцы glob или regexp'ы.
Флаг -iwrite предшествующий образцу передаёт в переменную interact_out(spawn_id) соответствующий заданному образцу (или eof).
Такие действия, как, break и continue воздействуют на управляющие конструкции (такие как, for, proc) обычным образом. Однако, return принуждает interact возвращать вызывающий оператор, пока inter_return не вызовет return на вызвавшего оператора. На пример, если "proc foo" вызовет interact с исполняемым, в последствии, inter_return, то, будет возвращён proc foo. (Это означает, что interact вызывает интерпретатор интерактивно печатающий return, который, в свою очередь, продолжает работу interact, пока inter_return не вернёт его вызывателя.)
В процессе работы interact'а, используется raw режим, и все символы могут быть переданы текущему процессу. Если текущий процесс не получит контролирующие его работу сигналы, он может быть остановлен отправкой стоп сигнала (по умолчанию ^Z). Для перезапуска, надо отправить сигнал продолжения (примерно, как "kill -CONT <pid>"). Если Вы действительно хотите отправить SIGSTOP к процессу (с помощью ^Z), в начале сделайте спаун csh и затем запустите Вашу программу. В другом случае, если Вам понадобиться отправить SIGSTOP из Expect'а самому себе, вначале вызовите интерпретатор (например, с использованием символа escape), и затем нажмите ^Z.
Пара строка-тело может быть использована как сокращённая запись для избежания входа в интерпретатор и интерактивного исполнения команд. Предыдущий терминальный режим используется пока выполняется тело пары строка-тело.
Для скорости, по умолчанию, действия исполняются в raw режиме.Флаг -reset перезагружает терминал. Помните, что символы введённые во время переключения режима, могут быть потеряны (неудачная особенность драйвера терминала на некоторых системах). Существует только одна причина по которой придётся использовать -reset: если Ваши действия надо запускать в cook режиме.
Флаг -echo отправляет символы которые сравниваются с последующими образцами, обратно к процессу, который генерирует каждый прочитываемый символ. Полезно в случае если пользователю надо видеть обратную связь от частично напечатанных образцов.
Если образец будучи отображемым с помощью echo, но не подпадает под сравнение, то, в этом случае символы отправляются к порождённому процессу. Если порождённый процесс в свою очередь отображает их с помощью echo, то в этом случае пользователь увидит их дважды. -echo подходит к использованию только в ситуациях, когда пользователь не завершил образец. На пример, следующий отрывок от rftp, представляет собой рекурсивный-ftp сценарий, где пользователю выдаётся приглашение на ввод ~g, ~p или ~l, для рекурсивного получения, установки или листинга директории. Этот пример очень далёк от обычных ftp команд, так как, пользователь врядли будет набирать символ ~ присутствующий везде, ожидая ошибку, в этом случае, возможно, будет игнорироваться любой результат.
interact {
    -echo ~g {getcurdirectory 1}
    -echo ~l {getcurdirectory 0}
    -echo ~p {putcurdirectory}
}
Флаг -nobuffer отправляет символы которые соответствуют следующим образцам на читаемом как символы, выводе процессора.
Полезно в том случае, когда Вы хотите получить вывод программы в качестве образца. На пример, следующий фрагмент используется для определения набранного пользователем телефонного номера (модем типа Hayes). Каждое "atd" записывается сценарием в лог как одна строка.
proc lognumber {} {
    interact -nobuffer -re "(.*)\r" return
    puts $log "[exec date]: dialed $interact_out(1,string)"
}

interact -nobuffer "atd" lognumber


В течение работы interact'а, предыдущее использование log_user игнорируется. В частности, interact позволяет вводить свой вывод в логи (отправляя его на стандартный вывод) для избежания выполнения interact'а вслепую.
Флаг -o применяет последующие пары клавиша-тело на вывод текущего процесса. Удобно применять, на пример, при работе с хостами, отправляющими нежелательные символы в течении telnet сессии.
По умолчанию, interact ожидает от пользователя ввода в stdin и читает stdout от внутреннего Expect процесса. Флаг -u (для "пользователя") заставляет interact наблюдать за вводом от пользователя, как от процесса названного как аргумент (который должен быть порождённым id).
В этом случае два разных процесса объединяются без использования явного цикла. Для удобства в отладке, отладочные сообщения Expect'а отправляются в stderr (или stdout для ведения логов и отладочной информации). По той же причине, команда интерпретатора будет интерактивно читать из stdin.
На пример, следующий фрагмент создаёт процесс регистрации в системе. Затем сценарий обращается к пользователю (не отображаясь на экране), и под конец подключается. Конечно, другой процесс может заменить процесс регистрации в системе. Например, оболочка может не поддерживать процесс ввода пароля.
spawn login
set login $spawn_id
spawn tip modem
# dial back out to user
# connect user to login
interact -u $login
Отправка вывода на многочисленные процессы, а также просмотр всего списка порождённых id осуществляется с помощью флага -output. Ввод для группы порождённых id определяется флагом -input. (Оба флага -input и -output могут получить списки от флага -i в команде expect, за исключением некоторого_порождённого_id не обозначенного в interact'е). Все последующие флаги и строки (или образцы) применяются к этому вводу до тех пор, пока не встретится другой -input флаг. Если -input не встретился, -output подразумевает "-input $user_spawn_id -output". (Аналогично, с образцами которые не имеют -input'а.) Если определён один -input, то аннулируется $user_spawn_id. Если определён второй -input, то аннулируется $spawn_id. Можно определить дополнительные флаги -input.
Два неявных, вводящих какие-либо данные, процесса, по умолчанию, имеют вывод определённый как $spawn_id и $user_spawn_id. Если в тексте встречается флаг -input без флага -output, то символы от такого процесса не будут учитываться.
Флаг -i вводит замещение для текущего spawn_id, когда не используются другие -input или -output флаги. Флаг -i подразумевает флаг -o.
Также можно изменять интерактивные процессы, с использованием косвенных порождённых id. (Непрямые id описываются в секции команды expect.) Косвенное порождение id может быть объявлено с помощью флагов -i, -u, -input и -output.
interpreter [args]
позволяет пользователю интерактивно вводить команды Expect'а и Tcl'я. Результат каждой команды отображается на экране.
Такие действия как break и continue не воздействуют на управляющие структуры. Однако return возвращается к вызвавшему его оператору, пока inter_return заставляет interpreter вернуться к вызывателю. Например, если "proc foo" вызывает interpreter который затем выполняет действие inter_return, то, произойдёт возвращение к proc foo. Другие команды предоставляют возможность вводить новые команды интерпретатора.
По умолчанию, приглашение содержит два целых значения. Первое значение описывает глубину стека вычисления (то есть, как много раз может быть вызвано Tcl_Eval). Второе целочисленное значение - это идентификатор истории Tcl. Приглашение можно установить объявлением вызова процедуры "prompt1", который возвращает величину следующего приглашения. Если оператор содержит открытые кавычки, скобки, то второе приглашение (по умолчанию "+> ") выдаётся с новой строки. Второе приглашение может быть установлено объявлением процедуры "prompt2".
Во время работы интерпретатор'а используется режим cooked, даже если вызвавший его оператор используется в raw режиме.
Если stdin закрыт, интерпретатор вернётя если используется -eof флаг, в этом случае вводится следующий аргумент.
log_file [args] [[-a] file]
Если объявлено имя файла, log_file будет записывать копию сессии (начиная с команды log_file) в этот файл. log_file остановит запись если нет переданных аргументов. Предыдущие лог файлы будут закрыты.
Взамен имени файла, можно использовать идентификатор файла из языка Tcl, с помощью флагов -open или -leaveopen. Аналогично команде spawn. (Для дополнительной информации смотрите spawn.)
Флаг -a ведёт логгирование вывода, который был запрещён командой log_user.
По умолчанию, команда log_file добавляет вывод к старым файлам, не урезая их. Для урезания файлов, используйте флаг -noappend.
Флаг -info возвращает описание не информативных аргументов от log_file.
log_user -info|0|1
По умолчанию, диалог send/expect логгируется в stdout (и в логфайл, если он открыт). Ведение логов в stdout отключается спомощью команды "log_user 0" и включается командой "log_user 1".При этом, ведение логов в лог файл остаётся без изменений.
Флаг -info в команде log_user возвращает описание большинства недавних не-информативных аргументов.
match_max [-d] [-i spawn_id] [size]
указывает размер буфера (в байтах) используемый непосредственно командой expect. Без размера в аргументах, возвращается текущий размер.
С флагом -d, устанавливается значение по умолчанию. (Размер по умолчанию равен 2000.) С флагом -i, размер устанавливается для именованного порождённого id, в противном случае, размер установится для текущего процесса.
overlay [-# spawn_id] [-# spawn_id] [...] program [args]
выполняет программу с аргументами на месте завершенной текущей Expect программы. Аргументы с дефисом ставятся впереди команды, так, как если бы они были шеллом логина. Все spawn_id закрыты за исключением аргументов в имени. Всё отображается на именованные идентификаторы файлов.
Spawn_id отображаются на идентификаторах файлов по наследованию. На пример, следующая строка запускает шахматы (chess) и разрешает его контроль текущим процессом - допустим, шахматистом.
overlay -0 $spawn_id -1 $spawn_id -2 $spawn_id chess
Это более эффективно чем "interact -u", однако, здесь жертвуется способность исполнять программируемые взаимодействия, так как, процесс Expect'а не остаётся под контролем.
Помните, что таким образом, остаётся не контролируемый терминал. И если вы отключитесь или переобозначите стандартный ввод, программы, которые осуществляют контроль работы (оболочки, логини т.д.) будут работать не корректно.
parity [-d] [-i spawn_id] [value]
описывает независимую чётность или нечётность от вывода порождённого процесса. Если значение равно нулю, значит устанавливается чётность, в другом случае не чётно. При отсутствии аргументов, возвращается текущее значение.
С флагом -d, для чётности устанавливается значение по умолчанию.(Значение по умолчанию равно 1, т.е. нечётно.) С флагом -i значение чётности устанавливается для именованного порождённого id, в другом случае чётность устанавливается для текущего процесса.
remove_nulls [-d] [-i spawn_id] [value]
объявляет null'и удерживаемые или удаляемые с вывода порождённых процессов перед сравнением или сохранением в переменную expect_out или interact_out. Если значение равно 1, null'и удаляются. Если значение равно 0, null'и не удаляются. Если команда задана без аргументов, возвращается текущее значение.
С флагом -d, устанавливается значение по умолчанию. (Значение по умолчанию равно 1, т.е. null'и удаляются.) С флагом -i, значение устанавливается для именованного порождённого id, в другом случае оно устанавливается для текущего процесса.
Независимо от удаления или сохранения null'ей, Expect сохраняет null байты в лог и stdout.
send [-flags] строка
Отправляет строки текущему процессу. Например, команда:
send "hello world\r"
отправляет символы, h e l l o <пробел> w o r l d <return> текущему процессу. (Tcl включает printf-подобные команды (формат вызова) которые могут строить произвольные комплексные строки.)
Символы отправляются немедленно, хотя программы со строчно-буферизированным вводом не читают символы пока не будет отправлен символ возврата каретки. Символ возврата каретки обозначается как "\r".
Флаг -- заставляет интерпретировать следующий аргумент как строку, а не как флаг. Перед всеми строками может предшествовать "--" если они выглядят как флаг. Так обеспечивается надёжный механизм разделения переменных от флага. (Все строки начинающиеся с "-" зарезервированы для будущего использования.)
Флаг -i объявляет, что будет отправлена строка к именованному spawn_id. Если spawn_id является user_spawn_id, терминал находится в raw режиме, новые линии в строке переводятся к последовательности return-новая-линия, так, как если бы терминал находился в cooked режиме. Флаг -raw отключает такую трансляцию.
Флаг -null отправляет символ null (0 байтов). По умолчанию, отправляется один null. Целочисленное значение следующее за -null определяет количество отправляемых null'ей.
Флаг -break создаёт break условие. Работает при условии если порождённый id отмечает tty устройство открытым через "spawn-open". Если Вы используете такой порождённый процесс, как tip, вы должны использовать его (tip) соглашения для создания прерывания (break).
Флаг -s создаёт "медленно" отправляемый вывод, таким образом, избегаются такие ситуации, когда компьютер слишком быстро вводит данные в некий буфер, который был создан из расчёта на медленный ввод, характерный для человека. Такой вывод контролируется значением переменной "send_slow" которая получает список из двух элементов. Первый элемент - это целое число, которое описывает число автоматически отправляемых байтов. Второй элемент - реальное число, которое описывает задержку в секундах между отправкой символов. На пример, "set send_slow {10 .001}" в команде предваряемой с "send -s" и используемой для отправки строк с задержкой в 1 миллисекунду между каждыми 10-ю символами.
Флаг -h устанавливает вывод в человеко-подобный вид печати. Человеко-подобные задержки создаются между символами. (Алгоритм, основанный на программном обеспечении Weibull, с модификациями.) Этот вывод контролируется значениями переменной "send_human", которая принимает список из пяти элементов. Первые два элемента - среднее количество символов в секунду. Первый элемент используется по умолчанию. Секунда используется как окончание слова, для симуляции случайно происходящих пауз. Третий параметр - это мера изменчивости где .1 - сильная изменчивость, 1 - допустимое изменчивость, и 10 постоянная изменчивость. Предел - от нуля до бесконечности. Последние два параметра, соответственно, минимум и максимум промежуточное время. Минимум и максимум используются последними и "clip" - конечное время. Окончательное среднее значение может сильно различаться от заданного среднего, если минимальный и максимальный clip имеет недостаточные значения.
На пример, следующая команда эмулирует быстрый и последовательный набор:
set send_human {.1 .3 1 .05 2}
send -h "I'm hungry.  Let's do lunch."
когда следующий фрагмент может эмулировать состояние похмелья:
set send_human {.4 .4 .2 .5 100}
send -h "Goodd party lash night!"
Помните, что ошибки не симулируются, хотя вы можете установить коррекцию ошибочных ситуаций вставляя ошибки и корректируя их в аргументе команды send.
Флаги для отправки символов null, для отправки break'ов, для замедления вывода и для человеко-подобного вывода являются взаимоисключающими друг друга. Используется только последний объявленный флаг. Кроме того, без строковый аргумент может быть определён флагами для отправки символов null или break.
Предварение первого send'а expect'ом - хорошее правило. expect будет ждать пока запустится процесс, и никакого send'а не произойдёт. В частности, если первый send завершается перед запуском процесса, все Ваши отправленные данные могут быть проигнорированы. В ситуациях где интерактивные программы не выдают никакого приглашения на ввод, Вы можете предварять send паузой:
# Для защиты от хакеров,
# эта система не выдаёт приглашения на ввод пароля.
# Необходимо также ожидать 5 секунд перед вводом.
spawn telnet very.secure.gov
sleep 5
send password\r
exp_send - алиас для send. Если Вы используете Expectk или другой подобный вариант Expect'а в Tk среде, send объявляется с помощью Tk в совершенно другом ключе. exp_send обеспечивает совместимость между средами. Подобные алиасы созданы для остальных send команд Expect'а.
send_error [-flags] строка
подобно send'у, кроме того, что вывод отправляется в stderr быстрее чем текущему процессу.
send_log [--] строка
подобно send'у, кроме того, что строка отправляется только в логфайл (смотрите log_file.) Аргументы игнорируются если не открыт лог файл.
send_tty [-flags] строка
подобно send'у, отличается тем, что вывод отправляется в /dev/tty раньше, чем в текущий процесс.
send_user [-flags] строка
подобно send'у, отличается тем, что вывод отправляется в stdout раньше, чем в текущий процесс.
sleep секунды
принуждает сценарий засыпать на заданное количество секунд. Секунды целочисленное число. Прерывания (и события Tk если Вы используете Expectk) обрабатываются во время сна Expect'а.
spawn [аргументы] программа [аргументы]
создаёт новый процесс запускающий программу с аргументами. Stdin, stdout и stderr программы подключается к Expect'у, таким образом,можно читать и писать команды Expect'а. Подключение прерывается при закрытии или, если процесс сам закрыл другие идентификаторы файла.
Когда процесс запускается из spawn'а, переменная spawn_id устанавливается в дескриптор относящийся к процессу. Процесс описывается с помощью spawn_id, который считается текущим процессом. spawn_id может быть прочтён или записан.
user_spawn_id - глобальная переменная, содержащая дескриптор, который отмечается пользователем. На пример, когда spawn_id установится в это значение, expect ведёт себя подобно expect_user.
error_spawn_id глобальная переменная содержащая дескриптор, который устанавливается в стандартную ошибку. На пример, когда spawn_id установлен в это значение, send ведёт себя подобно send_error.
tty_spawn_id - это глобальная переменная содержащая дескриптор, который устанавливается в /dev/tty. Если /dev/tty не создан (например, в cron'е или batch сценарии), то в этом случае, tty_spawn_id не объявляется. Можно протестировать следующим образом:
if {[info vars tty_spawn_id]} {
    # /dev/tty создан
} else {
    # /dev/tty не создан
    # возможно в cron'е, batch'е, или сценарии
}


spawn возвращает UNIX id процесса. Если процесс не порождён, возвращается 0. Переменная spawn_out(slave,name) устанавливается в имя подчинённого pty устройства.
По умолчанию, spawn отображает имя команды и аргументы. Флаг -noecho предотвращает этот эффект.
Флаг -console перенаправляет вывод консоли в порождённый процесс. Поддерживается не во всех системах.
spawn работает непосредственно с pty, инициализированным тем же путём, что и пользовательский tty. Так обеспечивается инициализация всех настроек в "нормальное" состояние (в соответствии с stty(1)). Если объявлена переменная stty_init, то интерпретация идёт в стиле stty аргументов. Например, "setstty_init raw" переключает порождённые терминалы процессов в raw режим. -nottycopy пропускает инициализацию основанную на пользовательском tty. -nottyinit пропускает "нормальную" инициализацию.
Обычно, spawn даёт маленькое время для выполнения. Если Вы укажете spawn'у выдержать более значимое время, это может привести к зависанию pty. Число тестов запускаемых на pty, для избежания запутывания с блуждающими процессами. (Даётся 10 секунд блуждающему процессу.) Запуск Expect'а с опцией -d покажет pty с подозрительным статусом относящиеся к Expect'у. Если Вы не можете убить процессы с такими pty, то в этом случае Вам поможет перезагрузка.
Если спаун программы не завершился благополучно по причине сбоя exec(2) (например, если программа не существует), то в этом случае, будет возвращено сообщение об ошибке в командах interact или expect, так как будто программа была запущена и получено сообщение об ошибке на выводе. Такое поведение - следствие осуществления спауна. Спаун форкается, после порождённых процессов, не могущих осуществить связь с оригинальным процессом Expect'а через spawn_id.
Флаг -open интерпретирует следующий аргумент как идентификатор файла языка Tcl (т.е., возвращемый по открытию.) Порождённый id может быть использован как порождённый процесс. (Идентификатор файла больше не используется.) Так Вы можете обращаться к raw устройствам, файлам, и pipeline'ам как к порождённым процессам без использования pty. 0 означает наличие не ассоциированных процессов. Подключение к порождённому процессу закрывается также, как к идентификатору файла в языке Tcl. Флаг -leaveopen аналогичен флагу -open except'а, -leaveopen оставляет идентификатор открытым после закрытия порождённого id.
Флаг -pty держит открытым pty вне зависимости от существования порождённого процесса. Если ассоциированный процесс не существует, возвращается 0. Spawn_id устанавливается как обычно.
Переменная spawn_out(slave,fd) устанавливается в идентификатор файла соответствующий подчинённому pty. Закрыть можно с помощью "close -slave".
Флаг -ignore игнорирует имена сигналов в порождённых процессах. В противном случае сигналы обрабатываются в обычном режиме. Сигналы именуются также, как в команде trap, за исключением того, что каждый сигнал требует флаг разделения.
strace уровень
включает вывод на экран следующего выражения перед его исполнением. (Команда Tcl'я trace трассирует переменные.) Уровень указывает глубину трассировки в стеке вызовов. На пример, следующая команда запускает Expect с трассировкой не глубже 4-го уровня.
expect -c "strace 4" script.exp


Флаг -info включает отображение информации о не информативных аргументах.
stty аргументы
меняет режим терминала аналогично внешней stty команде.
По умолчанию, возможен контроль терминала. Другие терминалы могут быть доступны с добавлением "< /dev/tty..." к команде. (Помните, что аргументы не должны группироваться в один аргумент.)
Запросы о статусах возвращаются как результат команды. Если статус не получен и есть контроль над терминалом, то предыдущие статусы атрибутов raw и echo возвращаются в форме, которая может быть использована в команде.
На пример, аргументы raw или -cooked вводят терминал в raw режим.Аргументы -raw или cooked вводят терминал в режим cooked. Аргументы echo и -echo вводят терминал в echo и noecho режим соответственно.
Следующий пример иллюстрирует как временно отключить отображение производимых действий. Этот приём может быть использован в сценариях содержащих пароли. (За дополнительной информацией смотрите ниже, в разделе ТОНКОСТИ EXPECT'А.)
stty -echo
send_user "Password: "
expect_user -re "(.*)\n"
set password $expect_out(1,string)
stty echo


system аргументы
даёт аргументы для sh(1) во ввод, как если бы это была команда введённая с терминала. Expect ожидает пока завершится шелл. Возвращаемый от sh статус обрабатывается тем же путём, что и статусы exec.
В противовес exec'у, который перенаправляет stdin и stdout в сценарий, system не выполняет перенаправления (помимо указанных в строке). Таким образом, можно использовать программы которые обращаются напрямую в /dev/tty. По некоторым причинам, результаты команды system не записываются в лог.
timestamp [аргументы]
возвращает временной штамп. Без аргументов, возвращается число секунд с начала эпохи.
Флаг -format содержит строку которая задаёт образец формата времени согласно правилам POSIX для strftime. Например, %a заменяет аббревиатурой день недели (т.е., Sat). Вот весь список:
%a	 аббревиатура дня недели
%A	 полное названия дня недели
%b	 аббревиатура месяца
%B	 полное название месяца
%c	 следующие дата-время: Wed Oct  6 11:45:56 1993
%d	 день месяца (01-31)
%H	 час (00-23)
%I	 час (01-12)
%j	 день (001-366)
%m	 месяц (01-12)
%M	 минута (00-59)
%p	 am или pm
%S	 секунда (00-61)
%u	 день (1-7, Понедельник - первый день недели)
%U	 неделя (00-53, первое Воскресенье первый день первой недели)
%V	 неделя (01-53, стиль ISO 8601)
%w	 день (0-6)
%W	 неделя (00-53, первый Понедельник - первый день первой недели)
%x	 следующие дата-время: Wed Oct  6 1993
%X	 следующее время: 23:59:59
%y	 год (00-99)
%Y	 следующий год: 1993
%Z	 временная зона (или ничего если ничего не определено)
%%	 просто знак процента
Другие определения % не определены. Другие символы не затрагиваются. Поддерживается только локаль C.
Флаг -seconds выводит количество секунд прошедших от начала эпохи и используется как источник для других форматов. Иначе, используется текущее время.
Флаг -gmt переводит временной штамп во временную зону GMT. Без флагов, используется локальная временная зона.
trap [[команда] сигналы]
исполняет заданные команды на заданных сигналах. Команда исполняется в глобальном масштабе. Если команда отсутствует, возвращаются действия сигналов. Если команда - это строка SIG_IGN, то сигналы игнорируются. Если команда - строка SIG_DFL, сигналы являются результатом по-умолчанию system'а. сигналы являются или единственным сигналом или списком сигналов. Сигналы могут быть описаны цифровым или символьным видом, смотрите signal(3). Префикс "SIG" может быть опущен.
Без аргументов (или с аргументом -number), trap возвращает номер сигнала только что запущенной команды trap.
Флаг -code использует возвращённый код любой команды в Tcl, так, как будто он только запущен.
Флаг -interp оценивает команду используя интерпретатор во время запуска команды до объявления trap'а.
Флаг -name возвращает название сигнала только что исполненной команды trap.
Флаг -max возвращает самый большой числовой сигнал, который может быть установлен.
На пример, команда "trap {send_user "Ouch!"} SIGINT" будет печатать "Ouch!" при каждом нажатии ^C.
По умолчанию, SIGINT (генерируется нажатием клавиш ^C) и SIGTERM завершают работу Expect'а. Обусловлено это, следующей командой trap, создаваемой и запускаемой при запуске Expect'а.
trap exit {SIGINT SIGTERM}
Если Вы используете флаг -D для запуска отладчика, SIGINT объявляется заново для запуска интерактивного отладчика. Запускается следующая команда trap:
trap {exp_debug 1} SIGINT
Отладочный trap может быть изменён установкой переменной среды EXPECT_DEBUG_INIT в новой команде trap.
Конечно, Вы можете переопределить такое поведение, добавлением команды trap в Ваш сценарий. В частности, если Вы использовали команду "trap exit SIGINT", то отладочный trap также будет переопределён. Полезно использовать в том случае, если Вы хотите предотвратить получение пользователями доступа к отладчику.
Если Вы хотите определить Ваш собственный trap на SIGINT но оставить trap при запуске отладчика, используйте:
if {![exp_debug]} {trap mystuff SIGINT}
Как альтернатива, Вы можете использовать trap на отладчике, используя другие сигналы.
trap не даст Вам переопределять действия на SIGALRM как это реализовано внутри Expect'а. Команда disconnect устанавливает SIGALRM в SIG_IGN (игнорирование). Вы можете включить заново во время последующих spawn команд.
За дополнительной информацией смотрите signal(3).
wait [аргументы]
пауза в ожидании завершения порождённого процесса (или текущего процесса, если задано без имён).
wait обычно возвращает список из четырёх целых чисел. Первое целое число - pid ожидаемого процесса. Второе целое число - соответствующий порождённый id. Третье целое число - -1 если обнаружена ошибка операционной системы или 0 в противном случае. Если третье целое число равно 0, четвёртое целое число - статус возвращаемый порождённым процессом. Если третье число равно -1, четвёртое целое число - значение ошибки устанавливаемое операционной системой. Так же устанавливается глобальное значение errorCode.
Дополнительные элементы могут появляться в конце возвращаемого значения от команды wait. Опциональный пятый элемент обозначает класс информации. В настоящее время, доступные следующие значения для этого элемента: CHILDKILLED - в этом случае следующие два значения выдаются в C-стиле: имя сигнала и короткое текстовое описание.
Флаг -i ждёт пока процессу не установится соответствующий именованный spawn_id (НЕ id процесса). Внутри хэндлера SIGCHLD, возможен wait для порождённого процесса с использованием порождённого id -1.
Флаг -nowait ждёт немедленного возвращения с индикацией результата wait. Когда процесс существует (позже), он автоматически исчезнет без явного wait'а.
Команда wait может быть использован также для форкнутых процессов через аргументы "-i -1". Отличие: используется с порождёнными процессами, и может выполняться в любое время. Не осуществляется контроль над умершими процессами. Однако, возвращаемое значение может быть проверено для id процесса.

БИБЛИОТЕКИ

Expect знает о двух встроенных библиотеках для Expect сценариев. Они находятся в директориях объявленных в переменных exp_library и exp_exec_library. Оба содержат файлы утилиты, которые могут быть использованы другими сценариями.
exp_library содержит архитектурно-независимые файлы. exp_exec_library содержит архитектурно-зависимые файлы. Зависящие от Вашей системы, обе директории могут быть полностью пустыми. Наличие файла $exp_exec_library/cat-buffers описывает где, по умолчанию, находиться буфер /bin/cat.

АВТО-ФОРМАТ

Возможно использование vgrind'а для авто-форматирования Expect сценариев. Предполагая, что Expect установлен корректно, возможна следующая команда:
vgrind -lexpect file

ПРИМЕРЫ

Конечно, сразу непонятно как применить всё что описано в этом мануале. Было бы неплохо читать и исполнять примеры в директории с примерами поставляемыми вместе с Expect'ом. Некоторые из них являются настоящими программами. Другие простые иллюстрации определённых приёмов, и конечно, некоторых хитрых приёмов. INSTALL файл содержит краткий обзор этих программ.
Записки об Expect'е (читайте СМОТРИТЕ ТАКЖЕ) также весьма полезны. Пока некоторые записки содержат синтаксис соответствующий ранним версиям Expect'а, сопровождающие объяснения всё ещё имеют силу и содержат больше информации чем эта страница.

ОГОВОРКИ

Возможен конфликт расширений с именем команды Expect'а. К примеру, send служит в Tk для совершенно других целей. По этой причине, большинство комманд Expect'а доступно в виде "exp_XXXX". Команды и переменные начинающиеся с "exp", "inter", "spawn" и "timeout" не имеют алиасов. Используйте расширенные имена команд, если Вам нужна совместимость между средами.
Expect имеет весьма либеральные взгляды на обзор. В частности, интерпретатор пытается определить переменные, читаемые командами, внутри локального блока программы и при не нахождении в локальных местах, ищет в глобальном разрезе. Таким образом, не нужно размещать "global timeout" в каждой процедуре, где используется expect. Другой случай: переменные находящиеся в локальной сфере (процедура, подпрограмма и т.д., за исключением "global"ных переменных). Большинство общих проблем возникает тогда, когда spawn исполняется в процедуре. За пределами процедуры, spawn_id уничтожается. Поэтому, если Вам нужен spawn_id используйте конструкцию "global spawn_id".
Если Вы неможете включить свойство мультиспауна (т.е., Ваша система не поддерживает select (BSD *.*), poll (SVR>2) или что-то похожее), то Expect сможет контролировать только один процесс в единицу времени. В этом случае, не пытайтесь установливать spawn_id, или выполнять процессы через exec пока работает порождённый процесс. Кроме того, Вы не сможете expect'ить несколько процессов (включая пользователя как один процесс) в один и тот же момент.
Параметры терминала могут серьёзно влиять на сценарии. На пример, если сценарий написан для просмотра эха (echo), то после подавления эха сценарий может дать непредсказуемый результат. По этой причине, Expect устанавливает параметры терминала по-умолчанию. К сожалению, этот факт может иметь неприятные последствия для других программ. В качестве примера можно привести следующее: оболочка emacs'а сама меняет "обычное" отображение: новые строки отображаются в новых строках без возврата каретки, и эхо отключается. Таким образом, с помощью Emacs'а можно редактировать строку ввода. К несчастью, Expect не может угадать это.
Вы можете указать Expect'у не изменять настройки терминалов, но в этом случае Вам нужно быть очень аккуратными при написании сценариев для таких сред. В случае Emacs'а, приходится зависеть от эха и отображений конца строки.
Команды, принимающие аргументы в виде единственного списка (варианты expect'а и interact) используют эвристику для решения вопроса: задан ли один или несколько аргументов. Эвристика может подвести в случае когда список на самом деле представляют единственный аргумент, в который входит несколько \n'ов, без пробелов между ними. Это кажется достаточно невероятным, однако, аргумент "-nobrace" может использоваться для указания восприятия единственного аргумента как, собственно, единственный аргумент. Вот такая вот рекурсия, товарищи. Предположительно, используется с кодом созданным машиной. Аналогично, -brace заставляет принимать один аргумент как составные образцы/действия.

БАГИ

Был соблазн назвать программу как "sex" (как сокращение от "Smart EXec" или "Send-EXpect"), но доброе начало (или Пуританизм) взяло верх.
На некоторых системах, при порождении шелла, выводятся сообщения о невозможности получении доступа к tty, но шелл всё же запускается. Это значит, что Ваша система имеет механизмы получения контроля tty, о которых не известно Expect'у. Если Вы столкнётесь с такими проблемами, пожалуйста, сообщите об этом мне.
Ultrix 4.1 (самая ранняя из последних версий) считает таймауты около 1000000 равными нулю.
Цифровой UNIX 4.0A (и возможно другие версии) отказываются распределять pty'ки если Вы определили SIGCHLD хэндлер. Смотрите страницу grantpt за дополнительной информацией.
IRIX 6.0 не корректно работает с разрешениями pty, так как, Expect пытается распределять pty первоначально используемые кем-то другим и при этом терпит неудачу. Обновитесь до IRIX 6.1.
Telnet (проверено только под SunOS 4.1.2) зависает если переменная TERM не установлена. Эта проблема проявляется под cron'ом, и в cgi скриптах, которые не устанавливают TERM. Таким образом, Вы должны явно установить эту переменную. Достаточно установить в какое-либо значение! Следующий пример должен подойти для многих случаев.
set env(TERM) vt100
Также (проверено только под BSDI BSD/OS 3.1 i386) зависает если не установлены переменные SHELL и HOME. Эта проблема выявляется при работе под cron'ом, и в cgi сценариях, которые явно не определяют значения этих переменных среды. Таким образом, Вы должны явно их установить - не обязательно в правильное значение. Достаточно просто установить во что нибудь! Следующий пример должен подойти ко многим случаям.
set env(SHELL) /bin/sh
set env(HOME) /usr/local/bin


Некоторые реализации pty'ков устроены так, что после от 10 до 15 секунд простоя (точное число зависит от реализации) ядро не читает вывод и закрывает процесс с дескриптором файла. Программа подобная этой:
spawn date
sleep 20
expect
не будет работать. Чтобы избежать этого, вызывайте не-интерактивные программы с помощью exec'а раньше чем spawn. Такие ситуации пока возможны, но, на практике Я никогда не сталкивался с ситуацией потери конечного вывода интерактивной программы.
С другой стороны, pty'ки Cray UNICOS'а отбрасывают и не читают вывод сразу после того, как процесс закроет дескриптор файла. Я написал отчёт об этом в Cray и они работают над этой проблемой.
Иногда требуется пауза между приглашением и ответом, например, при смене UART настроек tty интерфейса или соответствующего бод рэйта при просмотре start/stop битов. Обычно, всё это требует sleep'а на секунду или две. Более продвинутая технология: повторять запрос пока железо не примет ввод. Следующий пример использует обе стратегии:
send "speed 9600\r";
sleep 1
expect {
       timeout {send "\r"; exp_continue}
       $prompt
       }
ловушка -code не работает с другой командой, устанавливающей такие события Tcl'я, как например, sleep. Проблема заключается в том, что Tcl не принимает коды возврата с асинхронных хэндлеров событий. Эту проблему можно обойти установкой флага в код ловушки. Затем проверять флаг сразу после команды (то есть, после sleep).
Команда expect_background игнорирует аргумент -timeout и изначально не имеет понятия таймаутов.


ТОНКОСТИ EXPECT'А

Есть пара не интуитивно понятных тонкостей при работе с Expect'ом. Эта секция предназначена для освещения таких вопросов.
Главная проблема expect'a - это определение приглашения оболочки. Решается эта проблема различными способами для различных пользователей и различных оболочек, переносимый сценарий автоматизации rlogin'а может быть сложной задачей без знания приглашения оболочки. Разумным решением может быть описание приглашения в регулярном выражении, в переменной оболочки EXPECT_PROMPT. Также можно использовать следующий код. Если EXPECT_PROMPT не существует, код может правильно отработать.
set prompt "(%|#|\\$) $"	;# приглашение по умолчанию
catch {set prompt $env(EXPECT_PROMPT)}
expect -re $prompt
Я одобряю написание таких образцов expect'а, которые включают в себя концовку отличную от той, что Вы ожидаете получить. Этот метод помогает избежать раннего ответа на, ещё не заданный, вопрос. Может возникнуть такая ситуация, в которой вопрос ещё не задан, но Ваш сценарий уже ответил. В этом случае Ваш ответ может уйти в никуда. Другими словами, результирующий диалог может быть правильным, но может выглядеть беспорядочно.
Большинство приглашений включают символы пробела в конце. На пример, приглашение от ftp выглядит так: 'f', 't', 'p', '>' и <пробел>. Для определения этого приглашения, Вы должны учитывать каждый этот символ. Весьма распространена ошибка, в которой не учитывается пробел. Явно указывайте пробел.
Если Вы используете образец вида X*, * - будет соответствовать всему выводу принятому от X'а и до конца вывода. Это высказывание звучит само собой разумеющимся, но отчасти непонятна фраза "до конца вывода". Тут есть зависимость от скорости компьютера и организации Ввода/Вывода ядра и драйвера устройства.
В частности, люди привыкли видеть вывод программы, поступающим огромными порциями (частями), когда в действительности большинство программ производят вывод в одну строку за единицу времени. Допуская такой случай, образец *, в предыдущем абзаце, может означать конец текущей строки, хотя на самом деле вывод ещё не завершён.
expect не имеет возможности узначть что вывод ещё не завершён. Поэтому, Вы сами должны учесть эти тонкости в задаваемых образцах.
Вообще, всё зависящее от строко-ориентированной буферизации, является костылём. Если программа предназначена именно на такой вид работы, то системная ошибка в любой момент может вызвать прерывание выводимых строк. Будет хорошим стилем предугадывать несколько последних строк приглашения при написании образцов.
Если Вы ждёте совпадения образца в последнем выводе программы и программа выдаёт что-то другое взамен ожидаемого, Вы не сможете определить вывод программы с помощью ключевого слова timeout. Причина этого - expect не допускает таймаута - взамен этого он (expect) определяет eof (конец файла). Используйте конец файла взамен таймаута. А ещё лучше - используйте оба варианта. В этом случае, при перемещении строки, Вам не надо будет менять образец.
Новые строки, обычно, конвертируются в возврат каретки, в свою очередь перевод строки генерируется драйвером терминала. Таким образом, если Вам нужен образец явно соответствующий двум строкам, например, printf("foo\nbar"), то, нужно использовать образец "foo\r\nbar".
Аналогичный перевод строки происходит при чтении с пользователя, через expect_user. В этом случае, при нажатии Enter'а, происходит переход на новую строку. Если Expect передаёт этот вывод программе, которая устанавливает терминал в raw режим (подобно telnet'у), то тут возникнет проблема: программа будет ожидать действительного возврата. (Некоторые программы автоматически транслируют новые строки в возврат каретки, но их мало.) К сожалению, это плохой путь нахождения вывода програм в терминале, установленном в raw режим.
Чем вручную заменять новые строки возвратом каретки, более лучшим решением будет команда "stty raw", которая остановит подобное замещение. Помните, что этот способ больше не является свойством редактирования строк.
interact подразумевает установку терминала в raw режим, поэтому такая проблема не возникает.
Часто используется для хранения паролей (или другой частной информации) в сценариях Expect'а. Так поступать не рекомендуется, так как, теоретически, доступ к компьютеру может получить кто угодно. Таким образом, интерактивный ввод паролей из сценария лучшее решение, чем по буквенная печать. Тем не менее, иногда по буквенная печать - единственная возможность работы.
К сожалению, файловая система UNIX не имеет прямого пути создания исполняемых, но не читаемых сценариев. Системы, поддерживающие setgid оболочки сценариев, могут косвенно эмулировать следующее:
Создать сценарий Expect'а (содержащий секретные данные) обычным путём. Установить разрешения в 750 (-rwxr-x---) и владельцем назначить доверенную группу, то есть, группу которая может читать этот сценарий. Если необходимо, создать новую группу для этих целей. Следующее, создать /bin/sh сценарий с разрешениями 2751 (-rwxr-s--x) принадлежащий к какой-либо другой группе.
Результатом будет сценарий, который может быть исполнен (и прочитан) кем угодно. Но, в этом сценарии будет возможность запустить сценарий Expect'а.

СМОТРИТЕ ТАКЖЕ

Tcl(3), libexpect(3)
"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" by Don Libes, pp. 602, ISBN 1-56592-090-2, O'Reilly and Associates, 1995.
"expect: Curing Those Uncontrollable Fits of Interactivity" by Don Libes, Proceedings of the Summer 1990 USENIX Conference, Anaheim, California, June 11-15, 1990.
"Using expect to Automate System Administration Tasks" by Don Libes, Proceedings of the 1990 USENIX Large Installation Systems Administration Conference, Colorado Springs, Colorado, October 17-19, 1990.
"Tcl: An Embeddable Command Language" by John Ousterhout, Proceedings of the Winter 1990 USENIX Conference, Washington, D.C., January 22-26, 1990.
"expect: Scripts for Controlling Interactive Programs" by Don Libes, Computing Systems, Vol. 4, No. 2, University of California Press Journals, November 1991.
"Regression Testing and Conformance Testing Interactive Programs", by Don Libes, Proceedings of the Summer 1992 USENIX Conference, pp. 135-144, San Antonio, TX, June 12-15, 1992.
"Kibitz - Connecting Multiple Interactive Programs Together", by Don Libes, Software - Practice & Experience, John Wiley & Sons, West Sussex, England, Vol. 23, No. 5, May, 1993.
"A Debugger for Tcl Applications", by Don Libes, Proceedings of the 1993 Tcl/Tk Workshop, Berkeley, CA, June 10-11, 1993.
"Использование Expect'а: Tcl ориентированный инструмент для Автоматизации Интерактивных Программ" за авторством Дона Либса, страницы 602, ISBN 1-56592-090-2, О'Рэйли и Ассоциации, 1995.
"expect: средство для работы с интерактивностью" за авторством Дона Либса, Тема на Летней Конференции 1990, Анахэйм, Калифорния, Июнь 11-15, 1990.
"Использование expect'а для Автоматизации Административно Системных Задач" за авторством Дона Либса, Тема на Конференции Администрирования Больших Устанавливаемых Систем USENIX 1990, Колорадо Спрингс, Колорадо, Октябрь 17-19, 1990.
"TCL: Встраиваемый Командный Язык" за авторством Джона Остерхаута, Тема на Зимней Конференции USENIX 1990, Январь 22-26, 1990.
"expect: Сценарии для Контроля Интерактивных Программ" за авторством Дона Либса, Вычислительные Системы, Том 4, Номер 2, Издательство Журналов Университета Калифорнии, Ноябрь 1991.
"Регрессивное Тестирование и Обозрение Тестируемых Интерактивных Программ", за авторством Дона Либса, Тема на Летней Конференции USENIX 1992, страницы 135-144, Сан Антонио, Техас, Июнь 12-15, 1992.
"Kibitz - Объединение Нескольких Интерактивных Программ", за авторством Дона Либса, Программное Обеспечение - Практика и Опыт, Джон Вилей и Сыновья, Западный Сассекс, Англия, Том 23, Номер 5, Май, 1993.
"Отладчик для Tcl приложений", за авторством Дона Либса, Тема на семинаре Tcl/Tk 1993, Калифорния, Июнь 10-11, 1993.

АВТОР

Дон Либс, Национальный Институт Стандартов и Технологий

АВТОРЫ

Выражаю благодарность Джону Остерхауту за Tcl и Скотту Пэйсли за поддержку. Спасибо Робу Савойю за код автоконфигурации Expect'а.
Файловые документы HISTORY содержат много информации о развитии expect'а. Они представляют собой интересное чтение и могут стать причиной дальнейшего погружения в программное обеспечения expect. Кроме того, выражаю благодарность людям приславшим мне багфиксы и помогавшими мне другими путями.
Разработка и внедрение Expect'а частично оплачено правительством Соединённых Штатов и поэтому (Expect) находится в публичном доступе. Однако, если Вам пригодились это программное обеспечение и документация, автор и Национальный Институт Стандартов и Технологий будет непротив, если Вы решите поддержать их деньгами.
29 Декабря 1994 EXPECT(1)