EXPECT(1) Общие команды EXPECT(1)
НАЗВАНИЕ
expect - программируемый диалог с интерактивными программами, Версия 5
СИНОПСИС
expect [ -dDinN ] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
ВВЕДЕНИЕ
Expect - это программа, которая "общается" с другими интерактивными программами в соответствии со сценарием. Следуя сценарию, Expect знает, чего ожидать от программы и какой должен быть правильный ответ. Интерпретируемый язык предоставляет ветвление и высокоуровневые управляющие структуры для управления диалогом. Кроме того, пользователь может взять контроль и взаимодействовать напрямую, когда это желательно, после чего вернуть контроль сценарию.
Expectk - это смесь Expect и Tk. Он работает так же, как Expect и Tk's wish. Expect также может использоваться напрямую в C или C++ (то есть, без Tcl). См. libexpect(3).
Название "Expect" происходит от идеи последовательностей send/expect, популяризированных uucp, kermit и другими программами управления модемом. Однако, в отличие от uucp, Expect обобщен, так что его можно запускать как пользовательскую команду с любой программой и задачей. Expect может фактически общаться с несколькими программами одновременно.
Например, вот некоторые вещи, которые может делать Expect:
• Заставить ваш компьютер набрать вам номер, чтобы вы могли войти, не платя за звонок.
• Запустить игру (например, rogue) и, если оптимальная конфигурация не появляется, перезапустить ее (снова и снова), пока она не появится, после чего передать контроль вам.
• Запустить fsck и в ответ на его вопросы отвечать "да", "нет" или вернуть контроль вам, на основе предопределенных критериев.
• Подключиться к другой сети или BBS (например, MCI Mail, CompuServe) и автоматически получить вашу почту, так чтобы она выглядела так, будто была отправлена на вашу локальную систему.
• Передать переменные среды, текущий каталог или любой вид информации через rlogin, telnet, tip, su, chgrp и т.д.
В общем, Expect полезен для запуска любой программы, которая требует взаимодействия между программой и пользователем. Всё, что нужно, - это то, чтобы взаимодействие могло быть охарактеризовано программно. Expect также может вернуть пользователю контроль (без остановки управляемой программы), если это желательно. Аналогично, пользователь может вернуть контроль сценарию в любое время.
ИСПОЛЬЗОВАНИЕ
Expect читает cmdfile для списка команд для выполнения. Expect также может быть вызван неявно на системах, которые поддерживают нотацию #!, отмечая сценарий исполняемым и делая первую строку в вашем сценарии:
#!/usr/local/bin/expect -f
Конечно, путь должен точно описывать, где находится Expect. /usr/local/bin - это просто пример.
Флаг -c предваряет команду для выполнения перед любыми в сценарии. Команда должна быть в кавычках, чтобы предотвратить её разбор оболочкой. Этот вариант может использоваться несколько раз. Несколько команд могут быть выполнены с одним -c, разделяя их точками с запятой. Команды выполняются в порядке их появления. (При использовании Expectk этот вариант указывается как -command.)
Флаг -d включает некоторый диагностический вывод, который в основном сообщает о внутренней активности команд, таких как expect и interact. Этот флаг имеет тот же эффект, что и "exp_internal 1" в начале сценария Expect, плюс выводится версия Expect. (Команда strace полезна для трассировки утверждений, а команда trace - для трассировки присваиваний переменных.) (При использовании Expectk этот вариант указывается как -diag.)
Флаг -D включает интерактивный отладчик. За ним должно следовать целочисленное значение. Отладчик возьмет контроль перед следующей процедурой Tcl, если значение ненулевое или если нажата ^C (или достигнута точка останова, или другая подходящая команда отладчика появляется в сценарии). См. файл README или СМ. НИЖЕ для получения дополнительной информации об отладчике. (При использовании Expectk этот вариант указывается как -Debug.)
Флаг -f предваряет файл, из которого читаются команды. Сам флаг необязателен, так как он полезен только при использовании нотации #!. (При использовании Expectk этот вариант указывается как -file.)
По умолчанию, файл команд читается в память и выполняется полностью. Иногда желательно читать файлы построчно. Например, stdin читается так. Чтобы заставить произвольные файлы обрабатываться таким образом, используйте флаг -b. (При использовании Expectk этот вариант указывается как -buffer.) Обратите внимание, что буферизация stdio может все равно происходить, однако это не должно вызвать проблем при чтении из fifo или stdin.
Если строка "-" предоставлена как имя файла, читается стандартный ввод. (Используйте "./-" для чтения из файла с именем "-".)
Флаг -i заставляет Expect интерактивно запрашивать команды вместо чтения их из файла. Запросы прерываются командой exit или по EOF. См. interpreter (ниже) для дополнительной информации. -i предполагается, если ни файл команд, ни -c не используются. (При использовании Expectk этот вариант указывается как -interactive.)
-- может использоваться для обозначения конца опций. Это полезно, если вы хотите передать аргумент, похожий на опцию, вашему сценарию, не интерпретируя его Expect. Это может быть полезно для размещения в строке #!, чтобы предотвратить интерпретацию, похожую на флаг, Expect. Например, следующее оставит исходные аргументы (включая имя сценария) в переменной argv.
#!/usr/local/bin/expect --
Обратите внимание, что обычные соглашения getopt(3) и execve(2) должны соблюдаться при добавлении аргументов в строку #!.
Файл $exp_library/expect.rc автоматически подключается, если присутствует, если не используется флаг -N. (При использовании Expectk этот вариант указывается как -NORC.) Сразу после этого файл ~/.expect.rc автоматически подключается, если не используется флаг -n. Если переменная среды DOTDIR определена, она рассматривается как каталог, и .expect.rc читается оттуда. (При использовании Expectk этот вариант указывается как -norc.) Это подключение происходит только после выполнения любых флагов -c.
-v заставляет Expect вывести свой номер версии и выйти. (Соответствующий флаг в Expectk, который использует длинные имена флагов, - -version.)
Необязательные args формируются в список и хранятся в переменной с именем 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 поддерживает дополнительные команды, описанные ниже. Если не указано иное, команды возвращают пустую строку.
Команды перечислены в алфавитном порядке, чтобы их можно было быстро найти. Однако, новые пользователи могут найти проще начать с описаний spawn, send, expect и interact, в этом порядке.
Обратите внимание, что лучшим введением в язык (как Expect, так и Tcl) является книга "Exploring Expect" (см. СМ. НИЖЕ). Примеры включены в эту страницу руководства, но они очень ограничены, поскольку эта страница предназначена в основном как справочный материал.
Обратите внимание, что в тексте этой страницы руководства "Expect" с заглавной буквой "E" относится к программе Expect, в то время как "expect" с прописной буквой "e" относится к команде expect внутри программы Expect.)
close [-slave] [-onexec 0|1] [-i spawn_id]
закрывает соединение с текущим процессом. Большинство интерактивных программ обнаружат EOF на stdin и выйдут; таким образом, close обычно достаточно, чтобы убить процесс. Флаг -i объявляет процесс для закрытия, соответствующий указанному spawn_id.
Как expect, так и interact обнаружат, когда текущий процесс выходит, и неявно выполнят close. Но если вы убьете процесс, скажем, "exec kill $pid", вам нужно будет явно вызвать close.
Флаг -onexec определяет, будет ли spawn id закрыт в любых новых запущенных процессах или если процесс будет наложен. Чтобы оставить spawn id открытым, используйте значение 0. Ненулевое целочисленное значение заставит spawn закрыться (по умолчанию) в любых новых процессах.
Флаг -slave закрывает ведомого, связанного со spawn id. (См. "spawn -pty".) Когда соединение закрыто, ведомый также автоматически закрывается, если он все еще открыт.
Независимо от того, закрывается ли соединение неявно или явно, вы должны вызвать wait, чтобы очистить соответствующий слот процесса ядра. close не вызывает wait, поскольку нет гарантии, что закрытие соединения процесса заставит его выйти. См. 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. С &, Expect не имеет возможности прочитать параметры терминала, поскольку терминал уже отключен к моменту, когда Expect получает контроль.
exit [-opts] [status]
заставляет 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 позволяет expect продолжить выполнение, а не вернуться, как обычно. По умолчанию exp_continue сбрасывает таймер тайм-аута. Флаг -continue_timer предотвращает перезапуск таймера. (См. expect для дополнительной информации.)
exp_internal [-f file] value
заставляет последующие команды отправлять диагностическую информацию, внутреннюю для Expect, в stderr, если value ненулевое. Этот вывод отключается, если value равно 0. Диагностическая информация включает каждый полученный символ и каждую попытку сопоставить текущий вывод с шаблонами.
Если предоставлен необязательный file, весь обычный и отладочный вывод записывается в этот файл (независимо от значения value). Любые предыдущие файлы диагностического вывода закрываются.
Флаг -info заставляет exp_internal вернуть описание наиболее недавних ненаденных аргументов.
exp_open [args] [-i spawn_id]
возвращает идентификатор файла Tcl, соответствующий исходному spawn_id. Идентификатор файла затем может использоваться так, как если бы он был открыт командой open Tcl. (Spawn_id больше не должен использоваться. Wait не должен выполняться.
Флаг -leaveopen оставляет spawn_id открытым для доступа через команды Expect. Wait должен выполняться на spawn_id.
exp_pid [-i spawn_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]
ожидает, пока один из шаблонов не совпадет с выводом запущенного процесса, не истечет указанный период времени или не будет обнаружен конец файла. Если конечное тело пустое, оно может быть omitted.
Шаблоны из наиболее недавней команды expect_before неявно используются перед любыми другими шаблонами. Шаблоны из наиболее недавней команды expect_after неявно используются после любых других шаблонов.
Если аргументы для всей команды expect требуют более одной строки, все аргументы могут быть "заключены в фигурные скобки" в одну, чтобы избежать завершения каждой строки обратной косой чертой. В этом одном случае будут происходить обычные подстановки Tcl, несмотря на фигурные скобки.
Если шаблон - это ключевое слово eof, соответствующее тело выполняется при конце файла. Если шаблон - это ключевое слово timeout, соответствующее тело выполняется при тайм-ауте. Если ключевое слово timeout не используется, при тайм-ауте выполняется неявное пустое действие. Период тайм-аута по умолчанию составляет 10 секунд, но может быть установлен, например, на 30, командой "set timeout 30". Бесконечный тайм-аут может быть обозначен значением -1. Если шаблон - это ключевое слово default, соответствующее тело выполняется при либо тайм-ауте, либо конце файла.
Если шаблон совпадает, то соответствующее тело выполняется. expect возвращает результат тела (или пустую строку, если ни один шаблон не совпал). В случае, если несколько шаблонов совпадают, используется тот, который появляется первым.
Каждый раз, когда приходит новый вывод, он сравнивается с каждым шаблоном в порядке их перечисления. Таким образом, вы можете проверить отсутствие совпадения, сделав последний шаблон чем-то, что гарантированно появится, таким как приглашение. В ситуациях, где нет приглашения, вы должны использовать timeout (как и если бы вы взаимодействовали вручную).
Шаблоны указываются тремя способами. По умолчанию шаблоны указываются так же, как в команде string match Tcl. (Такие шаблоны также похожи на регулярные выражения оболочки C, обычно называемые "glob" шаблонами). Флаг -gl может использоваться для защиты шаблонов, которые могут совпадать с флагами expect, от этого. Любые шаблоны, начинающиеся с "-", должны быть защищены таким образом. (Все строки, начинающиеся с "-", зарезервированы для будущих опций.)
Например, следующий фрагмент ищет успешный вход. (Обратите внимание, что abort предполагается процедурой, определенной где-то в сценарии.)
expect {
busy {puts busy\n ; exp_continue}
failed abort
"invalid password" abort
timeout abort
connected
}
Кавычки необходимы для четвертого шаблона, поскольку он содержит пробел, который в противном случае отделил бы шаблон от действия. Шаблоны с тем же действием (например, третьий и четвертый) требуют перечисления действий снова. Это можно избежать, используя шаблоны стиля regexp (см. ниже). Больше информации о формировании шаблонов стиля glob можно найти в руководстве Tcl.
Шаблоны стиля regexp следуют синтаксису, определенному командой regexp Tcl. Шаблоны regexp вводятся с флагом -re. Предыдущий пример можно переписать, используя regexp так:
expect {
busy {puts busy\n ; exp_continue}
-re "failed|invalid password" abort
timeout abort
connected
}
Оба типа шаблонов являются "непривязанными". Это означает, что шаблоны не должны совпадать с всей строкой, а могут начинать и заканчивать совпадение в любой точке строки (при условии, что все остальное совпадает). Используйте ^ для совпадения с началом строки и $ для совпадения с концом. Обратите внимание, что если вы не ждете конца строки, ваши ответы могут легко попасть в середину строки, поскольку они эхом отображаются из запущенного процесса. Хотя это все еще производит правильные результаты, вывод может выглядеть неестественно. Таким образом, использование $ рекомендуется, если вы можете точно описать символы в конце строки.
Обратите внимание, что во многих редакторах ^ и $ совпадают с началом и концом строк соответственно. Однако, поскольку expect не ориентирован на строки, эти символы совпадают с началом и концом данных (а не строк), которые в настоящее время находятся в буфере сопоставления expect. (Также см. примечание ниже о "системном расстройстве желудка.")
Флаг -ex заставляет шаблон совпадать как точную строку. Не производится интерпретация *, ^ и т.д. (хотя обычные соглашения Tcl должны все равно соблюдаться). Точные шаблоны всегда непривязанные.
Флаг -nocase заставляет прописные символы вывода сравниваться так, как если бы они были строчными. Шаблон не затрагивается.
При чтении вывода более 2000 байт могут заставить более ранние байты быть "забытыми". Это может быть изменено с помощью функции match_max. (Обратите внимание, что чрезмерно большие значения могут замедлить сопоставитель шаблонов.) Если patlist - full_buffer, соответствующее тело выполняется, если получено match_max байт и ни один другой шаблон не совпал. Независимо от того, используется ли ключевое слово full_buffer, забытые символы записываются в expect_out(buffer).
Если patlist - это ключевое слово null, и null разрешены (через команду remove_nulls), соответствующее тело выполняется, если совпадает один ASCII 0. Невозможно совпадать 0 байт через шаблоны glob или regexp.
При совпадении шаблона (или eof или full_buffer) любое совпавшее и ранее несопоставленное вывод сохраняется в переменной expect_out(buffer). До 9 подстрок regexp сохраняются в переменных 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" для удобства во время экспериментов).
Spawn id, связанный с совпавшим выводом (или eof или full_buffer), хранится в expect_out(spawn_id).
Флаг -timeout заставляет текущую команду expect использовать следующее значение как тайм-аут вместо значения переменной timeout.
По умолчанию, шаблоны совпадают с выводом из текущего процесса, однако флаг -i объявляет, что вывод из указанного списка spawn_id должен совпадать с последующими шаблонами (до следующего -i). Список spawn_id должен быть либо списком, разделенным пробелами, 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, связанных с any_spawn_id.
Флаг -i также может назвать глобальную переменную, в этом случае переменная читается для списка spawn_id. Переменная перечитывается всякий раз, когда она изменяется. Это предоставляет способ изменения источника I/O во время выполнения команды. Spawn id, предоставленные таким образом, называются "косвенными" spawn id.
Действия, такие как break и continue, заставляют управляющие структуры (т.е., for, proc) вести себя обычным образом. Команда exp_continue позволяет expect самому продолжить выполнение, а не вернуться, как обычно.
Это полезно для избежания явных циклов или повторяющихся утверждений 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
}
Например, следующий фрагмент может помочь пользователю направить взаимодействие, которое уже полностью автоматизировано. В этом случае терминал переводится в сырой режим. Если пользователь нажимает "+", переменная увеличивается. Если "p" нажимается, несколько возвратов отправляются процессу, возможно, чтобы подтолкнуть его каким-то образом, а "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, однако возвращается немедленно. Шаблоны тестируются всякий раз, когда приходит новый ввод. Шаблоны timeout и default бессмысленны для expect_background и тихо отбрасываются. В противном случае, команда expect_background использует шаблоны expect_before и expect_after так же, как expect.
Когда действия expect_background оцениваются, фоновый обработка для того же spawn id блокируется. Фоновая обработка разблокируется, когда действие завершается. Пока фоновый обработка заблокирована, возможно выполнить (передний план) expect на том же spawn id.
Невозможно выполнить expect во время разблокированного expect_background. Expect_background для определенного spawn id удаляется объявлением нового expect_background с тем же spawn id. Объявление expect_background без шаблона удаляет данный spawn id из возможности совпадения шаблонов в фоне.
expect_before [expect_args]
принимает те же аргументы, что и expect, однако возвращается немедленно. Пары шаблон-действие из наиболее недавнего expect_before с тем же spawn id неявно добавляются к любым последующим командам expect. Если шаблон совпадает, он трактуется так, как если бы он был указан в самой команде expect, и связанное тело выполняется в контексте команды expect. Если шаблоны из expect_before и expect могут совпасть, используется шаблон expect_before.
Если шаблон не указан, spawn id не проверяется на какие-либо шаблоны.
Если не переопределено флагом -i, шаблоны expect_before совпадают с spawn id, определенным в момент, когда команда expect_before была выполнена (не когда ее шаблон совпал).
Флаг -info заставляет expect_before вернуть текущие спецификации того, какие шаблоны он будет совпадать. По умолчанию, он сообщает о текущем spawn id. Можно указать необязательную спецификацию spawn id для информации об этом spawn id. Например
expect_before -info -i $proc
В лучшем случае может быть дана одна спецификация spawn id. Флаг -indirect подавляет прямые spawn id, которые приходят только из косвенных спецификаций.
Вместо спецификации spawn id флаг "-all" заставит "-info" сообщить обо всех spawn id.
Вывод флага -info может быть повторно использован как аргумент для expect_before.
expect_tty [expect_args]
как expect, но читает символы из /dev/tty (т.е. нажатия клавиш от пользователя). По умолчанию, чтение выполняется в режиме cooked. Таким образом, строки должны заканчиваться возвратом, чтобы expect увидел их. Это может быть изменено через stty (см. команду stty ниже).
expect_user [expect_args]
как expect, но читает символы из stdin (т.е. нажатия клавиш от пользователя). По умолчанию, чтение выполняется в режиме cooked. Таким образом, строки должны заканчиваться возвратом, чтобы expect увидел их. Это может быть изменено через stty (см. команду stty ниже).
fork создает новый процесс. Новый процесс - это точная копия текущего процесса Expect. При успешном выполнении fork возвращает 0 новому (дочернему) процессу и возвращает идентификатор процесса дочернего процесса родительскому процессу. При сбое (неизбежно из-за отсутствия ресурсов, например, пространства подкачки, памяти) fork возвращает -1 родительскому процессу, и дочерний процесс не создается.
Отделенные процессы выходят через команду exit, как и исходный процесс. Отделенным процессам разрешено писать в файлы журнала. Если вы не отключите отладку или журналирование в большинстве процессов, результат может быть запутанным.
Некоторые реализации pty могут путаться от нескольких читателей и писателей, даже на мгновение. Таким образом, безопаснее всего делать fork перед запуском процессов.
interact [string1 body1] ... [stringn [bodyn]]
передает контроль текущего процесса пользователю, так что нажатия клавиш отправляются текущему процессу, а stdout и stderr текущего процесса возвращаются.
Пары string-body могут быть указаны в качестве аргументов, в этом случае тело выполняется, когда соответствующая строка введена. (По умолчанию, строка не отправляется текущему процессу.) Команда interpreter предполагается, если конечное тело отсутствует.
Если аргументы для всей команды interact требуют более одной строки, все аргументы могут быть "заключены в фигурные скобки" в одну, чтобы избежать завершения каждой строки обратной косой чертой. В этом одном случае будут происходить обычные подстановки Tcl, несмотря на фигурные скобки.
Например, следующая команда запускает interact с следующими парами string-body определенными: Когда нажата ^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 [clock format [clock seconds]]."}
\003 exit
foo {send_user "bar"}
~~
}
В парах string-body строки совпадают в порядке их перечисления в аргументах. Строки, которые частично совпадают, не отправляются текущему процессу в ожидании остатка. Если затем вводятся символы, так что совпадение больше невозможно, только та часть строки отправляется процессу, которая не может начать другое совпадение. Таким образом, строки, которые являются подстроками частичных совпадений, могут совпасть позже, если исходные строки, которые пытались совпасть, в конечном итоге не совпадут.
По умолчанию, сопоставление строк точное без подстановочных знаков. (В контрасте, команда expect использует шаблоны стиля glob по умолчанию.) Флаг -ex может использоваться для защиты шаблонов, которые могут совпадать с флагами interact, от этого. Любые шаблоны, начинающиеся с "-", должны быть защищены таким образом. (Все строки, начинающиеся с "-", зарезервированы для будущих опций.)
Флаг -re заставляет строку интерпретироваться как шаблон стиля regexp. В этом случае, совпадающие подстроки хранятся в переменной interact_out так же, как expect хранит свой вывод в переменной expect_out. Флаг -indices аналогично поддерживается.
Шаблон eof вводит действие, которое выполняется при конце файла. Отдельный шаблон eof также может следовать за флагом -output, в этом случае он совпадает, если обнаружен конец файла при записи вывода. Действие eof по умолчанию - "return", так что interact просто возвращается при любом EOF.
Шаблон timeout вводит тайм-аут (в секундах) и действие, которое выполняется после того, как символы не читались в течение заданного времени. Шаблон timeout применяется к наиболее недавно указанному процессу. Нет значения тайм-аута по умолчанию. Специальная переменная "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) установиться на spawn_id, который совпал с шаблоном (или eof).
Действия, такие как break и continue, заставляют управляющие структуры (т.е., for, proc) вести себя обычным образом. Однако return заставляет interact вернуться к своему вызывающему, в то время как inter_return заставляет interact вызвать return в своем вызывающем. Например, если "proc foo" вызвал interact, который затем выполнил действие inter_return, proc foo вернется. (Это означает, что если interact вызывает interpreter, введя return интерактивно заставит interact продолжить, в то время как inter_return заставит interact вернуться к своему вызывающему.)
Во время interact используется сырой режим, чтобы все символы могли передаваться текущему процессу. Если текущий процесс не перехватывает сигналы управления задачами, он остановится, если получит сигнал остановки (по умолчанию ^Z). Чтобы перезапустить его, отправьте сигнал продолжения (например, "kill -CONT <pid>"). С другой стороны, если вы действительно хотите отправить SIGSTOP такому процессу (по ^Z), рассмотрите запуск csh сначала, а затем запуск своей программы. С другой стороны, если вы хотите отправить SIGSTOP Expect, сначала вызовите interpreter (возможно, используя символ экранирования), а затем нажмите ^Z.
Пары string-body могут использоваться как сокращение для избежания необходимости вводить interpreter и выполнять команды интерактивно. Предыдущий режим терминала используется, пока тело пары string-body выполняется.
Для скорости действия выполняются в сыром режиме по умолчанию. Флаг -reset сбрасывает терминал в режим, в котором он был до выполнения interact (неизбежно, режим cooked). Обратите внимание, что символы, введенные, когда режим переключается, могут быть потеряны (неудачная особенность драйвера терминала на некоторых системах). Единственная причина использования -reset - если ваше действие зависит от выполнения в режиме cooked.
Флаг -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 "[clock format [clock seconds]]: dialed $interact_out(1,string)"
}
interact -nobuffer "atd" lognumber
Во время interact предыдущее использование log_user игнорируется. В частности, interact заставит свой вывод логироваться (отправляться в стандартный вывод), поскольку предполагается, что пользователь не хочет взаимодействовать blindly.
Флаг -o заставляет любые последующие пары key-body применяться к выводу текущего процесса. Это может быть полезно, например, при работе с хостами, которые отправляют нежелательные символы во время сеанса telnet.
По умолчанию, interact ожидает, что пользователь будет писать в stdin и читать из stdout процесса Expect. Флаг -u (для "user") заставляет interact искать пользователя как процесс, именованный его аргументом (который должен быть spawn id).
Это позволяет двум несвязанным процессам соединиться вместе без использования явного цикла. Для помощи в отладке диагностика Expect всегда идет в stderr (или stdout для определенной информации журналирования и отладки). Для той же причины команда interpreter будет интерактивно читать из stdin.
Чтобы отправлять вывод нескольким процессам, перечислите каждый список spawn id, предваренный флагом -output. Ввод для группы spawn id вывода может быть определен списком spawn id, предваренным флагом -input. (Оба -input и -output могут принимать списки в той же форме, что и флаг -i в команде expect, за исключением того, что any_spawn_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.
Возможна смена процессов, с которыми взаимодействуют, используя косвенные spawn id. (Косвенные spawn id описаны в разделе команды expect.) Косвенные spawn id могут быть указаны с флагами -i, -u, -input или -output.
interpreter [args]
заставляет пользователя интерактивно запрашиваться на команды Expect и Tcl. Результат каждой команды печатается.
Действия, такие как break и continue, заставляют управляющие структуры (т.е., for, proc) вести себя обычным образом. Однако return заставляет interpreter вернуться к своему вызывающему, в то время как inter_return заставляет interpreter вызвать return в своем вызывающем. Например, если "proc foo" вызвал interpreter, который затем выполнил действие inter_return, proc foo вернется. Любая другая команда заставляет interpreter продолжить запрос новых команд.
По умолчанию, приглашение содержит два целых числа. Первое целое число описывает глубину стека оценки (т.е., сколько раз была вызвана Tcl_Eval). Второе целое число - идентификатор истории Tcl. Приглашение может быть установлено, определяя процедуру под названием "prompt1", чье возвращаемое значение становится следующим приглашением. Если утверждение имеет открытые кавычки, скобки, фигурные скобки или квадратные скобки, выдается вторичное приглашение (по умолчанию "+> "). Вторичное приглашение может быть установлено, определяя процедуру под названием "prompt2".
Во время interpreter используется режим cooked, даже если его вызывающий использовал сырой режим.
Если stdin закрыт, interpreter вернется, если не используется флаг -eof, в этом случае последующий аргумент вызывается.
log_file [args] [[-a] 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. Без аргумента size возвращается текущий размер.
С флагом -d устанавливается размер по умолчанию. (Начальный размер по умолчанию - 2000.) С флагом -i размер устанавливается для указанного spawn_id, иначе для текущего процесса.
overlay [-# spawn_id] [-# spawn_id] [...] program [args]
выполняет program args на месте текущей программы Expect, которая завершается. Обнаженный аргумент дефис заставляет дефис перед именем команды, как если бы это был логин-шелл. Все spawn_id закрываются, кроме тех, которые названы как аргументы. Эти отображаются на указанные идентификаторы файлов.
Spawn_id отображаются на идентификаторы файлов для нового процесса для наследования. Например, следующая строка запускает шахматы и позволяет контролировать его текущим процессом - скажем, мастером шахмат.
overlay -0 $spawn_id -1 $spawn_id -2 $spawn_id chess
Это эффективнее, чем "interact -u", однако, жертвуя возможностью программного взаимодействия, поскольку процесс Expect больше не контролирует.
Обратите внимание, что никакого управляющего терминала не предоставляется. Таким образом, если вы отключите или переместите стандартный ввод, программы, которые выполняют управление задачами (оболочки, login и т.д.) не будут работать правильно.
parity [-d] [-i spawn_id] [value]
определяет, следует ли сохранять или удалять четность из вывода запущенных процессов. Если value равно нулю, четность удаляется, иначе она не удаляется. Без аргумента value возвращается текущее значение.
С флагом -d устанавливается значение четности по умолчанию. (Начальное значение по умолчанию - 1, т.е. четность не удаляется.) С флагом -i значение четности устанавливается для указанного spawn_id, иначе для текущего процесса.
remove_nulls [-d] [-i spawn_id] [value]
определяет, следует ли сохранять или удалять нулевые символы из вывода запущенных процессов перед сопоставлением шаблонов или хранением в переменной expect_out или interact_out. Если value равно 1, нулевые символы удаляются. Если value равно 0, нулевые символы не удаляются. Без аргумента value возвращается текущее значение.
С флагом -d устанавливается значение по умолчанию. (Начальное значение по умолчанию - 1, т.е. нулевые символы удаляются.) С флагом -i значение устанавливается для указанного spawn_id, иначе для текущего процесса.
Независимо от того, удаляются ли нулевые символы, Expect будет записывать нулевые байты в журнал и stdout.
send [-flags] string
Отправляет string текущему процессу. Например, команда
send "hello world\r"
отправляет символы h e l l o <пробел> w o r l d <возврат> текущему процессу. (Tcl включает команду, похожую на printf (называемую format), которая может строить произвольно сложные строки.)
Символы отправляются немедленно, хотя программы с буферизованным вводом по строкам не прочитают символы до тех пор, пока не будет отправлен символ возврата. Символ возврата обозначается "\r".
Флаг -- заставляет следующий аргумент интерпретироваться как строку, а не как флаг. Любую строку можно предварить "--", независимо от того, выглядит ли она как флаг. Это обеспечивает надежный механизм для указания переменных строк без путаницы с теми, которые случайно выглядят как флаги. (Все строки, начинающиеся с "-", зарезервированы для будущих опций.)
Флаг -i объявляет, что строка должна быть отправлена указанному spawn_id. Если spawn_id - user_spawn_id и терминал в сыром режиме, новые строки в строке переводятся в последовательности возврата-новой строки, так что они выглядят так, как если бы терминал был в режиме cooked. Флаг -raw отключает этот перевод.
Флаг -null отправляет нулевые символы (0 байт). По умолчанию, отправляется один null. За ним может следовать целое число, указывающее, сколько null отправить.
Флаг -break генерирует условие разрыва. Это имеет смысл только если spawn id относится к устройству tty, открытому через "spawn -open". Если вы запустили процесс, такой как tip, вы должны использовать соглашение tip для генерации разрыва.
Флаг -s заставляет вывод отправляться "медленно", таким образом избегая распространенной ситуации, когда компьютер перевыполняет буфер ввода, предназначенный для человека, который никогда не перевыполнил бы тот же буфер. Этот вывод управляется значением переменной "send_slow", которая принимает список из двух элементов. Первый элемент - целое число, описывающее количество байт для отправки атомарно. Второй элемент - вещественное число, описывающее количество секунд, по которым атомарные отправки должны быть разделены. Например, "set send_slow {10 .001}" заставит "send -s" отправлять строки с 1 миллисекундой между каждой отправленной 10 символов.
Флаг -h заставляет вывод отправляться (в некоторой степени) как человек на самом деле печатает. Задержки, похожие на человеческие, появляются между символами. (Алгоритм основан на распределении Вейбулла, с изменениями, подходящими для этого конкретного применения.) Этот вывод управляется значением переменной "send_human", которая принимает список из пяти элементов. Первые два элемента - среднее время между символами в секундах. Первое используется по умолчанию. Второе используется в конце слов, чтобы симулировать тонкие паузы, которые иногда происходят в таких переходах. Третий параметр - мера изменчивости, где .1 довольно изменчиво, 1 разумно изменчиво, а 10 довольно неизменно. Экстремумы - 0 до бесконечности. Последние два параметра - соответственно, минимальное и максимальное время между. Минимум и максимум используются последними и "обрезают" конечное время. Конечное среднее может быть довольно другим от данного среднего, если минимум и максимум обрезают достаточно значений.
Как пример, следующая команда эмулирует быстрого и последовательного машиниста:
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.
Флаги для отправки нулевых символов, для отправки разрывов, для принудительного медленного вывода и для вывода стиля человека взаимоисключающие. Только тот, который указан последним, будет использоваться. Кроме того, аргумент строки не может быть указан с флагами для отправки нулевых символов или разрывов.
Хорошая идея предварить первое send процессу expect. Expect будет ждать, пока процесс запустится, в то время как send не может. В частности, если первое send завершается до запуска процесса, вы рискуете игнорированием ваших данных. В ситуациях, где интерактивные программы не предлагают начального приглашения, вы можете предварить send задержкой, как в:
# To avoid giving hackers hints on how to break in,
# this system does not prompt for an external password.
# Wait for 5 seconds for exec to complete
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] string
как send, кроме того, что вывод отправляется в stderr, а не текущему процессу.
send_log [--] string
как send, кроме того, что строка отправляется только в файл журнала (см. log_file.) Аргументы игнорируются, если файл журнала не открыт.
send_tty [-flags] string
как send, кроме того, что вывод отправляется в /dev/tty, а не текущему процессу.
send_user [-flags] string
как send, кроме того, что вывод отправляется в stdout, а не текущему процессу.
sleep seconds
заставляет сценарий спать в течение заданного количества секунд. Seconds может быть десятичным числом. Прерывания (и события Tk, если вы используете Expectk) обрабатываются, пока Expect спит.
spawn [args] program [args]
создает новый процесс, запускающий program args. Его stdin, stdout и stderr подключены к Expect, так что их можно читать и писать другими командами Expect. Соединение разрывается close или если процесс сам закрывает любой из идентификаторов файлов.
Когда процесс запущен 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, at или batch), то tty_spawn_id не определен. Это может быть проверено как:
if {[info vars tty_spawn_id]} {
# /dev/tty существует
} else {
# /dev/tty не существует
# вероятно, в сценарии cron, batch или at
}
spawn возвращает идентификатор процесса UNIX. Если процесс не запущен, возвращается 0. Переменная spawn_out(slave,name) устанавливается на имя устройства pty ведомого.
По умолчанию, spawn эхом отдает имя команды и аргументы. Флаг -noecho останавливает spawn от этого.
Флаг -console перенаправляет вывод консоли запущенному процессу. Это не поддерживается на всех системах.
Внутренно, spawn использует pty, инициализированную так же, как tty пользователя. Это дальше инициализируется так, что все настройки "здравы" (согласно stty(1)). Если переменная stty_init определена, она интерпретируется в стиле аргументов stty как дополнительная конфигурация. Например, "set stty_init raw" заставит терминалы дальнейших запущенных процессов начинаться в сыром режиме. -nottycopy пропускает инициализацию на основе tty пользователя. -nottyinit пропускает инициализацию "здравых".
Нормально, spawn занимает мало времени на выполнение. Если вы замечаете, что spawn занимает значительное время, он, вероятно, встречает pty, которые заклинены. Несколько тестов проводится на pty, чтобы избежать спутываний с заблудшими процессами. (Эти занимают 10 секунд на заклиненный pty.) Запуск Expect с опцией -d покажет, встречает ли Expect много pty в странных состояниях. Если вы не можете убить процессы, к которым эти pty прикреплены, ваш единственный выход может быть перезагрузкой.
Если program не может быть запущен успешно, потому что exec(2) терпит неудачу (например, когда program не существует), сообщение об ошибке будет возвращено следующей командой interact или expect, как если бы program запустилась и произвела сообщение об ошибке как вывод. Это поведение - естественное следствие реализации spawn. Внутренно, spawn форкает, после чего запущенный процесс не имеет способа общаться с исходным процессом Expect, кроме связи через spawn_id.
Флаг -open заставляет следующий аргумент интерпретироваться как идентификатор файла Tcl (т.е., возвращенный open.) Spawn id затем может использоваться так, как если бы это был запущенный процесс. (Идентификатор файла больше не должен использоваться.) Это позволяет вам обращаться с сырыми устройствами, файлами и конвейерами как с запущенными процессами без использования pty. 0 возвращается, чтобы указать, что нет связанного процесса. Когда соединение с запущенным процессом закрыто, идентификатор файла Tcl также закрывается. Флаг -leaveopen похож на -open, за исключением того, что -leaveopen заставляет идентификатор файла остаться открытым даже после закрытия spawn id.
Флаг -pty заставляет открыть pty, но не запускать процесс. 0 возвращается, чтобы указать, что нет связанного процесса. Spawn_id устанавливается как обычно.
Переменная spawn_out(slave,fd) устанавливается на идентификатор файла, соответствующий ведомому pty. Он может быть закрыт с помощью "close -slave".
Флаг -ignore называет сигнал, который должен игнорироваться в запущенном процессе. В противном случае, сигналы получают поведение по умолчанию. Сигналы называются так же, как в команде trap, за исключением того, что каждый сигнал требует отдельного флага.
strace level
заставляет следующие утверждения печататься перед выполнением. (Команда trace Tcl трассирует переменные.) Level указывает, насколько глубоко в стеке вызовов трассировать. Например, следующая команда запускает Expect, трассируя первые 4 уровня вызовов, но ни одного ниже.
expect -c "strace 4" script.exp
Флаг -info заставляет strace вернуть описание наиболее недавних ненаденных аргументов.
stty args
изменяет режимы терминала аналогично внешней команде stty.
По умолчанию, доступ к управляющему терминалу. Другие терминалы могут быть доступны, добавив "< /dev/tty..." к команде. (Обратите внимание, что аргументы не должны группироваться в один аргумент.)
Запросы статуса возвращают его как результат команды. Если статус не запрошен и доступ к управляющему терминалу, предыдущий статус атрибутов raw и echo возвращается в форме, которая может быть позже использована командой.
Например, аргументы raw или -cooked переводят терминал в сырой режим. Аргументы -raw или cooked переводят терминал в режим cooked. Аргументы echo и -echo переводят термиnal в режимы echo и noecho соответственно.
Следующий пример иллюстрирует, как временно отключить эхо. Это может использоваться в других автоматизированных сценариях, чтобы избежать внедрения паролей в них. (См. больше обсуждения этого в EXPECT HINTS ниже.)
stty -echo
send_user "Password: "
expect_user -re "(.*)\n"
set password $expect_out(1,string)
stty echo
system args
дает args оболочке sh(1) как ввод, как если бы это было введено как команда с терминала. Expect ждет, пока оболочка не завершится. Код возврата от sh обрабатывается так же, как exec обрабатывает свой код возврата.
В контрасте с exec, который перенаправляет stdin и stdout в сценарий, system не выполняет перенаправление (кроме указанного в строке). Таким образом, возможно использовать программы, которые должны напрямую обращаться к /dev/tty. По той же причине, результаты system не записываются в журнал.
timestamp [args]
возвращает временную метку. Без аргументов возвращается количество секунд с эпохи.
Флаг -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 заставляет вывод timestamp использовать часовой пояс GMT. Без флага используется локальный часовой пояс.
trap [[command] signals]
заставляет данную команду выполняться при будущей receipt любого из данных сигналов. Команда выполняется в глобальной области видимости. Если command отсутствует, возвращается действие сигнала. Если command - строка SIG_IGN, сигналы игнорируются. Если command - строка SIG_DFL, сигналы возвращаются к системному умолчанию. signals - либо один сигнал, либо список сигналов. Сигналы могут указываться численно или символически, как в signal(3). Префикс "SIG" может быть omitted.
Без аргументов (или с аргументом -number) trap возвращает номер сигнала команды trap, которая в настоящее время выполняется.
Флаг -code использует код возврата команды вместо того, что Tcl собирался вернуть, когда команда изначально запустилась.
Флаг -interp заставляет команду оцениваться с использованием интерпретатора, активного в момент, когда команда запустилась, а не когда trap был объявлен.
Флаг -name заставляет команду trap вернуть имя сигнала команды trap, которая в настоящее время выполняется.
Флаг -max заставляет команду trap вернуть наибольший номер сигнала, который можно установить.
Например, команда "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 [args]
задерживает, пока запущенный процесс (или текущий процесс, если ни один не назван) не завершится.
wait обычно возвращает список из четырех целых чисел. Первое целое число - pid процесса, который ожидался. Второе целое число - соответствующий spawn id. Третье целое число - -1, если произошла ошибка операционной системы, или 0 в противном случае. Если третье целое число было 0, четвертое целое число - статус, возвращенный запущенным процессом. Если третье целое число было -1, четвертое целое число - значение errno, установленное операционной системой. Также устанавливается глобальная переменная errorCode.
Дополнительные элементы могут появляться в конце возвращаемого значения от wait. Необязательный пятый элемент идентифицирует класс информации. В настоящее время, единственное возможное значение для этого элемента - CHILDKILLED, в этом случае следующие два значения - имя сигнала C-style и короткое текстовое описание.
Флаг -i объявляет процесс для ожидания, соответствующий указанному spawn_id (НЕ pid). Inside a SIGCHLD handler, it is possible to wait for any spawned process by using the spawn id -1.
Флаг -nowait заставляет wait вернуться немедленно с указанием успешного ожидания. Когда процесс выходит (позже), он автоматически исчезнет без необходимости явного wait.
Команда wait также может использоваться для ожидания отделенного процесса с аргументами "-i -1". В отличие от его использования с запущенными процессами, эта команда может выполняться в любое время. Нет контроля над тем, какой процесс собирается. Однако, возвращаемое значение может быть проверено на pid.
БИБЛИОТЕКИ
Expect автоматически знает о двух встроенных библиотеках для сценариев Expect. Они определяются каталогами, названными в переменных exp_library и exp_exec_library. Оба предназначены для содержа util файлов, которые могут использоваться другими сценариями.
exp_library содержит файлы, не зависящие от архитектуры. exp_exec_library содержит файлы, зависящие от архитектуры. В зависимости от вашей системы, оба каталога могут быть полностью пустыми. Существование файла $exp_exec_library/cat-buffers описывает, буферизует ли ваш /bin/cat по умолчанию.
ПРЕКРАСНОЕ ПЕЧАТАНИЕ
Определение vgrind доступно для красивого печати сценариев Expect. Предполагая, что определение vgrind, поставляемое с распространением Expect, правильно установлено, вы можете использовать его так:
vgrind -lexpect file
ПРИМЕРЫ
Это может быть не очевидно, как собрать все вместе, что описано в странице руководства. Я поощряю вас прочитать и попробовать примеры в каталоге example распространения Expect. Некоторые из них - реальные программы. Другие просто иллюстрируют определенные техники, и, конечно, пара - просто быстрые хаки. Файл INSTALL имеет быстрый обзор этих программ.
Статьи Expect (см. СМ. НИЖЕ) также полезны. Хотя некоторые статьи используют синтаксис, соответствующий более ранним версиям Expect, сопровождающие обоснования все еще действительны и уходят в гораздо большую деталь, чем эта страница руководства.
ПРЕДУПРЕЖДЕНИЯ
Расширения могут сталкиваться с именами команд Expect. Например, send определен Tk для совершенно другой цели. По этой причине, большинство команд Expect также доступны как "exp_XXXX". Команды и переменные, начинающиеся с "exp", "inter", "spawn" и "timeout", не имеют псевдонимов. Используйте расширенные имена команд, если вам нужна эта совместимость между средами.
Expect принимает довольно либеральный взгляд на область видимости. В частности, переменные, читаемые командами, специфичными для программы Expect, будут искаться сначала в локальной области видимости, и если не найдены, в глобальной области видимости. С другой стороны, переменные, которые пишутся, всегда в локальной области видимости (если команда "global" не была выдана). Наиболее распространенная проблема, которую это вызывает, - когда spawn выполняется в процедуре. Вне процедуры spawn_id больше не существует, так что запущенный процесс больше недоступен просто из-за области видимости. Добавьте "global spawn_id" к такой процедуре.
Если вы не можете включить возможность множественного запуска (т.е., ваша система не поддерживает ни select (BSD *.*), ни poll (SVR>2), ни эквивалент), Expect сможет контролировать только один процесс за раз. В этом случае, не пытайтесь установить spawn_id, ни запускать процессы через exec, пока запущенный процесс работает. Кроме того, вы не сможете expect от нескольких процессов (включая пользователя как один) одновременно.
Параметры терминала могут иметь большой эффект на сценарии. Например, если сценарий написан для поиска эха, он будет вести себя неправильно, если эхо отключено. По этой причине, Expect принуждает здравые параметры терминала по умолчанию. К сожалению, это может сделать вещи неприятными для других программ. Как пример, оболочка emacs хочет изменить "обычные" отображения: новые строки отображаются как новые строки вместо возврата-новых строк, и эхо отключено. Это позволяет использовать emacs для редактирования строки ввода. К сожалению, Expect не может угадать это.
Вы можете запросить, чтобы Expect не переопределял свои параметры терминала по умолчанию, но тогда вы должны быть очень осторожны при написании сценариев для таких сред. В случае emacs избегайте зависимости от вещей, таких как эхо и отображения конца строки.
Команды, которые принимают аргументы, заключенные в один список (варианты expect и interact), используют эвристику, чтобы решить, является ли список на самом деле одним аргументом или многими. Эвристика может потерпеть неудачу только в случае, когда список на самом деле представляет один аргумент, который имеет несколько встроенных \n с ненепробельными символами между ними. Это кажется достаточно неправдоподобным, однако аргумент "-nobrace" может использоваться, чтобы заставить один аргумент обрабатываться как один аргумент. Это, возможно, может использоваться с машинно-генерируемым кодом Expect. Аналогично, -brace заставляет один аргумент обрабатываться как несколько шаблонов/действий.
ОШИБКИ
Было очень соблазнительно назвать программу "sex" (для либо "Smart EXec", либо "Send-EXpect"), но здравый смысл (или, возможно, пуританство) победил.
На некоторых системах, когда оболочка запускается, она жалуется, что не может получить доступ к tty, но работает все равно. Это означает, что у вашей системы есть механизм получения управляющего tty, который Expect не знает. Пожалуйста, найдите, что это такое, и отправьте эту информацию мне.
Ultrix 4.1 (по крайней мере, последние версии здесь) считает тайм-ауты выше 1000000 эквивалентными 0.
Digital UNIX 4.0A (и, вероятно, другие версии) отказывается выделять ptys, если вы определяете обработчик SIGCHLD. См. страницу grantpt для дополнительной информации.
IRIX 6.0 не обрабатывает разрешения pty правильно, так что если Expect пытается выделить pty, ранее использованный кем-то другим, это терпит неудачу. Обновитесь до IRIX 6.1.
Telnet (проверено только под SunOS 4.1.2) зависает, если TERM не установлено. Это проблема под cron, at и в сценариях cgi, которые не определяют TERM. Таким образом, вы должны явно установить его - к какому типу обычно не имеет значения. Ему просто нужно быть установленным! Следующее, вероятно, достаточно для большинства случаев.
set env(TERM) vt100
Tip (проверено только под BSDI BSD/OS 3.1 i386) зависает, если SHELL и HOME не установлены. Это проблема под cron, at и в сценариях cgi, которые не определяют эти переменные среды. Таким образом, вы должны явно установить их - к какому типу обычно не имеет значения. Ему просто нужно быть установленным! Следующее, вероятно, достаточно для большинства случаев.
set env(SHELL) /bin/sh
set env(HOME) /usr/local/bin
Некоторые реализации ptys предназначены так, что ядро отбрасывает любой непрочитанный вывод после 10-15 секунд (фактическое число зависит от реализации) после того, как процесс закрыл дескриптор файла. Таким образом, программы Expect, такие как
spawn date
sleep 20
expect
потерпят неудачу. Чтобы избежать этого, вызывайте неинтерактивные программы с exec, а не spawn. Хотя такие ситуации мыслимы, на практике я никогда не сталкивался с ситуацией, в которой финальный вывод действительно интерактивной программы будет потерян из-за этого поведения.
С другой стороны, Cray UNICOS ptys отбрасывают любой непрочитанный вывод немедленно после того, как процесс закрыл дескриптор файла. Я сообщил об этом Cray, и они работают над исправлением.
Иногда требуется задержка между приглашением и ответом, такой как когда интерфейс tty изменяет настройки UART или сопоставляет скорости, смотря на стартовые/стоп-биты. Обычно, для всего этого требуется - спать секунду или две. Более надежная техника - повторять, пока оборудование не будет готово к приему ввода. Следующий пример использует обе стратегии:
send "speed 9600\r";
sleep 1
expect {
timeout {send "\r"; exp_continue}
$prompt
}
trap -code не будет работать с никакой командой, которая сидит в цикле событий Tcl, такой как sleep. Проблема в том, что в цикле событий Tcl отбрасывает коды возврата от асинхронных обработчиков событий. Решение - установить флаг в коде trap. Затем проверить флаг немедленно после команды (т.е., sleep).
Команда expect_background игнорирует аргументы -timeout и не имеет понятия о тайм-аутах в общем.
ПОДСКАЗКИ EXPECT
Есть пара вещей об Expect, которые могут быть неинтуитивными. Этот раздел пытается решить некоторые из этих вещей с парой предложений.
Общая проблема expect - как распознавать приглашения оболочки. Поскольку эти настраиваются по-разному разными людьми и разными оболочками, автоматизация rlogin в переносимом виде может быть сложной без знания приглашения. Разумная конвенция - заставить пользователей хранить регулярное выражение, описывающее их приглашение (в частности, конец) в переменной среды EXPECT_PROMPT. Код, такой как следующий, может использоваться. Если EXPECT_PROMPT не существует, код все еще имеет хороший шанс работать правильно.
set prompt "(%|#|\\$) $" ;# приглашение по умолчанию
catch {set prompt $env(EXPECT_PROMPT)}
expect -re $prompt
Я поощряю вас писать шаблоны expect, которые включают конец того, чего вы ожидаете увидеть. Это избегает возможности ответить на вопрос до того, как увидите всю вещь. Кроме того, хотя вы, возможно, сможете ответить на вопросы до того, как увидите их полностью, если вы ответите рано, ваш ответ может появиться эхом отраженным посреди вопроса. Другими словами, результирующий диалог будет правильным, но будет выглядеть перемешанным.
Большинство приглашений включают символ пробела в конце. Например, приглашение от ftp - 'f', 't', 'p', '>' и <пробел>. Чтобы совпадать с этим приглашением, вы должны учитывать каждый из этих символов. Это распространенная ошибка не включать пробел. Добавьте пробел явно.
Если вы используете шаблон формы X*, * совпадет со всем выводом, полученным от конца X до последней вещи, полученной. Это звучит интуитивно, но может быть несколько запутанным, потому что фраза "последняя вещь, полученная" может варьироваться в зависимости от скорости компьютера и обработки I/O как ядром, так и драйвером устройства.
В частности, люди склонны видеть вывод программы, прибывающий в огромных частях (атомарно), когда на самом деле большинство программ производит вывод построчно. Предполагая, что это так, * в шаблоне предыдущего абзаца может совпасть только с концом текущей строки, даже если кажется, что есть больше, потому что в момент совпадения это был весь вывод, который был получен.
expect не имеет способа знать, что дальнейший вывод идет, если ваш шаблон специально учитывает это.
Новые строки обычно переводятся в последовательности возврата, новой строки, когда выводится драйвером терминала. Таким образом, если вы хотите шаблон, который явно совпадает с двумя строками, от, скажем, printf("foo\nbar"), вы должны использовать шаблон "foo\r\nbar".
Похожий перевод происходит при чтении от пользователя, через expect_user. В этом случае, когда вы нажимаете return, это будет переведено в новую строку. Если Expect затем передаст это запущенной программе, которая устанавливает свой терминал в сырой режим (как telnet), возникнет проблема, поскольку программа ожидает истинный return. (Некоторые программы на самом деле прощают, что они автоматически переводят новые строки в возвраты, но большинство не.) К сожалению, нет способа узнать, что программа поставила свой терминал в сырой режим.
Скорее всего, ручное замещение новых строк возвратами, решение - использовать команду "stty raw", которая остановит перевод. Обратите внимание, однако, что это означает, что вы больше не получите функции редактирования cooked.
interact неявно устанавливает ваш терминал в сырой режим, так что эта проблема не возникнет тогда.
Часто полезно хранить пароли (или другую конфиденциальную информацию) в сценариях Expect. Это не рекомендуется, поскольку все, что хранится на компьютере, подвержено доступу кем угодно. Таким образом, интерактивное запрос паролей из сценария - умная идея, чем внедрение их буквально. Тем не менее, иногда такое внедрение - единственная возможность.
К сожалению, файловая система UNIX не имеет прямого способа создания сценариев, которые исполняемы, но нечитаемы. Системы, которые поддерживают сценарии shell 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" Дона Libes, стр. 602, ISBN 1-56592-090-2, O'Reilly и Associates, 1995.
"expect: Curing Those Uncontrollable Fits of Interactivity" Дона Libes, Proceedings of the Summer 1990 USENIX Conference, Anaheim, California, June 11-15, 1990.
"Using expect to Automate System Administration Tasks" Дона Libes, Proceedings of the 1990 USENIX Large Installation Systems Administration Conference, Colorado Springs, Colorado, October 17-19, 1990.
"Tcl: An Embeddable Command Language" Джона Ousterhout, Proceedings of the Winter 1990 USENIX Conference, Washington, D.C., January 22-26, 1990.
"expect: Scripts for Controlling Interactive Programs" Дона Libes, Computing Systems, Vol. 4, No. 2, University of California Press Journals, November 1991.
"Regression Testing and Conformance Testing Interactive Programs", Дона Libes, Proceedings of the Summer 1992 USENIX Conference, pp. 135-144, San Antonio, TX, June 12-15, 1992.
"Kibitz - Connecting Multiple Interactive Programs Together", Дона Libes, Software - Practice & Experience, John Wiley & Sons, West Sussex, England, Vol. 23, No. 5, May, 1993.
"A Debugger for Tcl Applications", Дона Libes, Proceedings of the 1993 Tcl/Tk Workshop, Berkeley, CA, June 10-11, 1993.
АВТОР
Дон Libes, National Institute of Standards and Technology
ПОСЛАНИЯ
Благодарности Джону Ousterhout за Tcl и Скотту Paisley за вдохновение. Благодарности людям, упомянутым в нем, которые отправили мне исправления ошибок и оказали другую помощь.
Дизайн и реализация Expect были оплачены частично правительством США и, следовательно, находятся в общественном домене. Однако автор и NIST хотели бы признания, если эта программа и документация или их части используются.
EXPECT(1) General Commands Manual EXPECT(1)
NAME
expect - programmed dialogue with interactive programs, Version 5
SYNOPSIS
expect [ -dDinN ] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
INTRODUCTION
Expect is a program that "talks" to other interactive programs accord‐
ing to a script. Following the script, Expect knows what can be ex‐
pected from a program and what the correct response should be. An in‐
terpreted language provides branching and high-level control structures
to direct the dialogue. In addition, the user can take control and in‐
teract directly when desired, afterward returning control to the
script.
Expectk is a mixture of Expect and Tk. It behaves just like Expect and
Tk's wish. Expect can also be used directly in C or C++ (that is,
without Tcl). See libexpect(3).
The name "Expect" comes from the idea of send/expect sequences popular‐
ized by uucp, kermit and other modem control programs. However unlike
uucp, Expect is generalized so that it can be run as a user-level com‐
mand with any program and task in mind. Expect can actually talk to
several programs at the same time.
For example, here are some things Expect can do:
• Cause your computer to dial you back, so that you can login
without paying for the call.
• Start a game (e.g., rogue) and if the optimal configuration
doesn't appear, restart it (again and again) until it does,
then hand over control to you.
• Run fsck, and in response to its questions, answer "yes",
"no" or give control back to you, based on predetermined
criteria.
• Connect to another network or BBS (e.g., MCI Mail, Com‐
puServe) and automatically retrieve your mail so that it ap‐
pears as if it was originally sent to your local system.
• Carry environment variables, current directory, or any kind
of information across rlogin, telnet, tip, su, chgrp, etc.
There are a variety of reasons why the shell cannot perform these
tasks. (Try, you'll see.) All are possible with Expect.
In general, Expect is useful for running any program which requires in‐
teraction between the program and the user. All that is necessary is
that the interaction can be characterized programmatically. Expect can
also give the user back control (without halting the program being con‐
trolled) if desired. Similarly, the user can return control to the
script at any time.
USAGE
Expect reads cmdfile for a list of commands to execute. Expect may
also be invoked implicitly on systems which support the #! notation by
marking the script executable, and making the first line in your
script:
#!/usr/local/bin/expect -f
Of course, the path must accurately describe where Expect lives.
/usr/local/bin is just an example.
The -c flag prefaces a command to be executed before any in the script.
The command should be quoted to prevent being broken up by the shell.
This option may be used multiple times. Multiple commands may be exe‐
cuted with a single -c by separating them with semicolons. Commands
are executed in the order they appear. (When using Expectk, this op‐
tion is specified as -command.)
The -d flag enables some diagnostic output, which primarily reports in‐
ternal activity of commands such as expect and interact. This flag has
the same effect as "exp_internal 1" at the beginning of an Expect
script, plus the version of Expect is printed. (The strace command is
useful for tracing statements, and the trace command is useful for
tracing variable assignments.) (When using Expectk, this option is
specified as -diag.)
The -D flag enables an interactive debugger. An integer value should
follow. The debugger will take control before the next Tcl procedure
if the value is non-zero or if a ^C is pressed (or a breakpoint is hit,
or other appropriate debugger command appears in the script). See the
README file or SEE ALSO (below) for more information on the debugger.
(When using Expectk, this option is specified as -Debug.)
The -f flag prefaces a file from which to read commands from. The flag
itself is optional as it is only useful when using the #! notation (see
above), so that other arguments may be supplied on the command line.
(When using Expectk, this option is specified as -file.)
By default, the command file is read into memory and executed in its
entirety. It is occasionally desirable to read files one line at a
time. For example, stdin is read this way. In order to force arbi‐
trary files to be handled this way, use the -b flag. (When using Ex‐
pectk, this option is specified as -buffer.) Note that stdio-buffering
may still take place however this shouldn't cause problems when reading
from a fifo or stdin.
If the string "-" is supplied as a filename, standard input is read in‐
stead. (Use "./-" to read from a file actually named "-".)
The -i flag causes Expect to interactively prompt for commands instead
of reading them from a file. Prompting is terminated via the exit com‐
mand or upon EOF. See interpreter (below) for more information. -i is
assumed if neither a command file nor -c is used. (When using Expectk,
this option is specified as -interactive.)
-- may be used to delimit the end of the options. This is useful if
you want to pass an option-like argument to your script without it be‐
ing interpreted by Expect. This can usefully be placed in the #! line
to prevent any flag-like interpretation by Expect. For example, the
following will leave the original arguments (including the script name)
in the variable argv.
#!/usr/local/bin/expect --
Note that the usual getopt(3) and execve(2) conventions must be ob‐
served when adding arguments to the #! line.
The file $exp_library/expect.rc is sourced automatically if present,
unless the -N flag is used. (When using Expectk, this option is speci‐
fied as -NORC.) Immediately after this, the file ~/.expect.rc is
sourced automatically, unless the -n flag is used. If the environment
variable DOTDIR is defined, it is treated as a directory and .expect.rc
is read from there. (When using Expectk, this option is specified as
-norc.) This sourcing occurs only after executing any -c flags.
-v causes Expect to print its version number and exit. (The corre‐
sponding flag in Expectk, which uses long flag names, is -version.)
Optional args are constructed into a list and stored in the variable
named argv. argc is initialized to the length of argv.
argv0 is defined to be the name of the script (or binary if no script
is used). For example, the following prints out the name of the script
and the first three arguments:
send_user "$argv0 [lrange $argv 0 2]\n"
COMMANDS
Expect uses Tcl (Tool Command Language). Tcl provides control flow
(e.g., if, for, break), expression evaluation and several other fea‐
tures such as recursion, procedure definition, etc. Commands used here
but not defined (e.g., set, if, exec) are Tcl commands (see tcl(3)).
Expect supports additional commands, described below. Unless otherwise
specified, commands return the empty string.
Commands are listed alphabetically so that they can be quickly located.
However, new users may find it easier to start by reading the descrip‐
tions of spawn, send, expect, and interact, in that order.
Note that the best introduction to the language (both Expect and Tcl)
is provided in the book "Exploring Expect" (see SEE ALSO below). Exam‐
ples are included in this man page but they are very limited since this
man page is meant primarily as reference material.
Note that in the text of this man page, "Expect" with an uppercase "E"
refers to the Expect program while "expect" with a lower-case "e"
refers to the expect command within the Expect program.)
close [-slave] [-onexec 0|1] [-i spawn_id]
closes the connection to the current process. Most interactive
programs will detect EOF on their stdin and exit; thus close usu‐
ally suffices to kill the process as well. The -i flag declares
the process to close corresponding to the named spawn_id.
Both expect and interact will detect when the current process ex‐
its and implicitly do a close. But if you kill the process by,
say, "exec kill $pid", you will need to explicitly call close.
The -onexec flag determines whether the spawn id will be closed
in any new spawned processes or if the process is overlayed. To
leave a spawn id open, use the value 0. A non-zero integer value
will force the spawn closed (the default) in any new processes.
The -slave flag closes the slave associated with the spawn id.
(See "spawn -pty".) When the connection is closed, the slave is
automatically closed as well if still open.
No matter whether the connection is closed implicitly or explic‐
itly, you should call wait to clear up the corresponding kernel
process slot. close does not call wait since there is no guaran‐
tee that closing a process connection will cause it to exit. See
wait below for more info.
debug [[-now] 0|1]
controls a Tcl debugger allowing you to step through statements,
set breakpoints, etc.
With no arguments, a 1 is returned if the debugger is not run‐
ning, otherwise a 0 is returned.
With a 1 argument, the debugger is started. With a 0 argument,
the debugger is stopped. If a 1 argument is preceded by the -now
flag, the debugger is started immediately (i.e., in the middle of
the debug command itself). Otherwise, the debugger is started
with the next Tcl statement.
The debug command does not change any traps. Compare this to
starting Expect with the -D flag (see above).
See the README file or SEE ALSO (below) for more information on
the debugger.
disconnect
disconnects a forked process from the terminal. It continues
running in the background. The process is given its own process
group (if possible). Standard I/O is redirected to /dev/null.
The following fragment uses disconnect to continue running the
script in the background.
if {[fork]!=0} exit
disconnect
. . .
The following script reads a password, and then runs a program
every hour that demands a password each time it is run. The
script supplies the password so that you only have to type it
once. (See the stty command which demonstrates how to turn off
password echoing.)
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
}
An advantage to using disconnect over the shell asynchronous
process feature (&) is that Expect can save the terminal parame‐
ters prior to disconnection, and then later apply them to new
ptys. With &, Expect does not have a chance to read the termi‐
nal's parameters since the terminal is already disconnected by
the time Expect receives control.
exit [-opts] [status]
causes Expect to exit or otherwise prepare to do so.
The -onexit flag causes the next argument to be used as an exit
handler. Without an argument, the current exit handler is re‐
turned.
The -noexit flag causes Expect to prepare to exit but stop short
of actually returning control to the operating system. The user-
defined exit handler is run as well as Expect's own internal han‐
dlers. No further Expect commands should be executed. This is
useful if you are running Expect with other Tcl extensions. The
current interpreter (and main window if in the Tk environment)
remain so that other Tcl extensions can clean up. If Expect's
exit is called again (however this might occur), the handlers are
not rerun.
Upon exiting, all connections to spawned processes are closed.
Closure will be detected as an EOF by spawned processes. exit
takes no other actions beyond what the normal _exit(2) procedure
does. Thus, spawned processes that do not check for EOF may con‐
tinue to run. (A variety of conditions are important to deter‐
mining, for example, what signals a spawned process will be sent,
but these are system-dependent, typically documented under
exit(3).) Spawned processes that continue to run will be inher‐
ited by init.
status (or 0 if not specified) is returned as the exit status of
Expect. exit is implicitly executed if the end of the script is
reached.
exp_continue [-continue_timer]
The command exp_continue allows expect itself to continue execut‐
ing rather than returning as it normally would. By default
exp_continue resets the timeout timer. The -continue_timer flag
prevents timer from being restarted. (See expect for more infor‐
mation.)
exp_internal [-f file] value
causes further commands to send diagnostic information internal
to Expect to stderr if value is non-zero. This output is dis‐
abled if value is 0. The diagnostic information includes every
character received, and every attempt made to match the current
output against the patterns.
If the optional file is supplied, all normal and debugging output
is written to that file (regardless of the value of value). Any
previous diagnostic output file is closed.
The -info flag causes exp_internal to return a description of the
most recent non-info arguments given.
exp_open [args] [-i spawn_id]
returns a Tcl file identifier that corresponds to the original
spawn id. The file identifier can then be used as if it were
opened by Tcl's open command. (The spawn id should no longer be
used. A wait should not be executed.
The -leaveopen flag leaves the spawn id open for access through
Expect commands. A wait must be executed on the spawn id.
exp_pid [-i spawn_id]
returns the process id corresponding to the currently spawned
process. If the -i flag is used, the pid returned corresponds to
that of the given spawn id.
exp_send
is an alias for send.
exp_send_error
is an alias for send_error.
exp_send_log
is an alias for send_log.
exp_send_tty
is an alias for send_tty.
exp_send_user
is an alias for send_user.
exp_version [[-exit] version]
is useful for assuring that the script is compatible with the
current version of Expect.
With no arguments, the current version of Expect is returned.
This version may then be encoded in your script. If you actually
know that you are not using features of recent versions, you can
specify an earlier version.
Versions consist of three numbers separated by dots. First is
the major number. Scripts written for versions of Expect with a
different major number will almost certainly not work. exp_ver‐
sion returns an error if the major numbers do not match.
Second is the minor number. Scripts written for a version with a
greater minor number than the current version may depend upon
some new feature and might not run. exp_version returns an error
if the major numbers match, but the script minor number is
greater than that of the running Expect.
Third is a number that plays no part in the version comparison.
However, it is incremented when the Expect software distribution
is changed in any way, such as by additional documentation or op‐
timization. It is reset to 0 upon each new minor version.
With the -exit flag, Expect prints an error and exits if the ver‐
sion is out of date.
expect [[-opts] pat1 body1] ... [-opts] patn [bodyn]
waits until one of the patterns matches the output of a spawned
process, a specified time period has passed, or an end-of-file is
seen. If the final body is empty, it may be omitted.
Patterns from the most recent expect_before command are implic‐
itly used before any other patterns. Patterns from the most re‐
cent expect_after command are implicitly used after any other
patterns.
If the arguments to the entire expect statement require more than
one line, all the arguments may be "braced" into one so as to
avoid terminating each line with a backslash. In this one case,
the usual Tcl substitutions will occur despite the braces.
If a pattern is the keyword eof, the corresponding body is exe‐
cuted upon end-of-file. If a pattern is the keyword timeout, the
corresponding body is executed upon timeout. If no timeout key‐
word is used, an implicit null action is executed upon timeout.
The default timeout period is 10 seconds but may be set, for ex‐
ample to 30, by the command "set timeout 30". An infinite time‐
out may be designated by the value -1. If a pattern is the key‐
word default, the corresponding body is executed upon either
timeout or end-of-file.
If a pattern matches, then the corresponding body is executed.
expect returns the result of the body (or the empty string if no
pattern matched). In the event that multiple patterns match, the
one appearing first is used to select a body.
Each time new output arrives, it is compared to each pattern in
the order they are listed. Thus, you may test for absence of a
match by making the last pattern something guaranteed to appear,
such as a prompt. In situations where there is no prompt, you
must use timeout (just like you would if you were interacting
manually).
Patterns are specified in three ways. By default, patterns are
specified as with Tcl's string match command. (Such patterns are
also similar to C-shell regular expressions usually referred to
as "glob" patterns). The -gl flag may may be used to protect
patterns that might otherwise match expect flags from doing so.
Any pattern beginning with a "-" should be protected this way.
(All strings starting with "-" are reserved for future options.)
For example, the following fragment looks for a successful login.
(Note that abort is presumed to be a procedure defined elsewhere
in the script.)
expect {
busy {puts busy\n ; exp_continue}
failed abort
"invalid password" abort
timeout abort
connected
}
Quotes are necessary on the fourth pattern since it contains a
space, which would otherwise separate the pattern from the ac‐
tion. Patterns with the same action (such as the 3rd and 4th)
require listing the actions again. This can be avoid by using
regexp-style patterns (see below). More information on forming
glob-style patterns can be found in the Tcl manual.
Regexp-style patterns follow the syntax defined by Tcl's regexp
(short for "regular expression") command. regexp patterns are
introduced with the flag -re. The previous example can be
rewritten using a regexp as:
expect {
busy {puts busy\n ; exp_continue}
-re "failed|invalid password" abort
timeout abort
connected
}
Both types of patterns are "unanchored". This means that pat‐
terns do not have to match the entire string, but can begin and
end the match anywhere in the string (as long as everything else
matches). Use ^ to match the beginning of a string, and $ to
match the end. Note that if you do not wait for the end of a
string, your responses can easily end up in the middle of the
string as they are echoed from the spawned process. While still
producing correct results, the output can look unnatural. Thus,
use of $ is encouraged if you can exactly describe the characters
at the end of a string.
Note that in many editors, the ^ and $ match the beginning and
end of lines respectively. However, because expect is not line
oriented, these characters match the beginning and end of the
data (as opposed to lines) currently in the expect matching buf‐
fer. (Also, see the note below on "system indigestion.")
The -ex flag causes the pattern to be matched as an "exact"
string. No interpretation of *, ^, etc is made (although the
usual Tcl conventions must still be observed). Exact patterns
are always unanchored.
The -nocase flag causes uppercase characters of the output to
compare as if they were lowercase characters. The pattern is not
affected.
While reading output, more than 2000 bytes can force earlier
bytes to be "forgotten". This may be changed with the function
match_max. (Note that excessively large values can slow down the
pattern matcher.) If patlist is full_buffer, the corresponding
body is executed if match_max bytes have been received and no
other patterns have matched. Whether or not the full_buffer key‐
word is used, the forgotten characters are written to ex‐
pect_out(buffer).
If patlist is the keyword null, and nulls are allowed (via the
remove_nulls command), the corresponding body is executed if a
single ASCII 0 is matched. It is not possible to match 0 bytes
via glob or regexp patterns.
Upon matching a pattern (or eof or full_buffer), any matching and
previously unmatched output is saved in the variable ex‐
pect_out(buffer). Up to 9 regexp substring matches are saved in
the variables expect_out(1,string) through expect_out(9,string).
If the -indices flag is used before a pattern, the starting and
ending indices (in a form suitable for lrange) of the 10 strings
are stored in the variables expect_out(X,start) and ex‐
pect_out(X,end) where X is a digit, corresponds to the substring
position in the buffer. 0 refers to strings which matched the
entire pattern and is generated for glob patterns as well as reg‐
exp patterns. For example, if a process has produced output of
"abcdefgh\n", the result of:
expect "cd"
is as if the following statements had executed:
set expect_out(0,string) cd
set expect_out(buffer) abcd
and "efgh\n" is left in the output buffer. If a process produced
the output "abbbcabkkkka\n", the result of:
expect -indices -re "b(b*).*(k+)"
is as if the following statements had executed:
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
and "a\n" is left in the output buffer. The pattern "*" (and -re
".*") will flush the output buffer without reading any more out‐
put from the process.
Normally, the matched output is discarded from Expect's internal
buffers. This may be prevented by prefixing a pattern with the
-notransfer flag. This flag is especially useful in experiment‐
ing (and can be abbreviated to "-not" for convenience while ex‐
perimenting).
The spawn id associated with the matching output (or eof or
full_buffer) is stored in expect_out(spawn_id).
The -timeout flag causes the current expect command to use the
following value as a timeout instead of using the value of the
timeout variable.
By default, patterns are matched against output from the current
process, however the -i flag declares the output from the named
spawn_id list be matched against any following patterns (up to
the next -i). The spawn_id list should either be a whitespace
separated list of spawn_ids or a variable referring to such a
list of spawn_ids.
For example, the following example waits for "connected" from the
current process, or "busy", "failed" or "invalid password" from
the spawn_id named by $proc2.
expect {
-i $proc2 busy {puts busy\n ; exp_continue}
-re "failed|invalid password" abort
timeout abort
connected
}
The value of the global variable any_spawn_id may be used to
match patterns to any spawn_ids that are named with all other -i
flags in the current expect command. The spawn_id from a -i flag
with no associated pattern (i.e., followed immediately by another
-i) is made available to any other patterns in the same expect
command associated with any_spawn_id.
The -i flag may also name a global variable in which case the
variable is read for a list of spawn ids. The variable is reread
whenever it changes. This provides a way of changing the I/O
source while the command is in execution. Spawn ids provided
this way are called "indirect" spawn ids.
Actions such as break and continue cause control structures
(i.e., for, proc) to behave in the usual way. The command
exp_continue allows expect itself to continue executing rather
than returning as it normally would.
This is useful for avoiding explicit loops or repeated expect
statements. The following example is part of a fragment to auto‐
mate rlogin. The exp_continue avoids having to write a second
expect statement (to look for the prompt again) if the rlogin
prompts for a password.
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
}
For example, the following fragment might help a user guide an
interaction that is already totally automated. In this case, the
terminal is put into raw mode. If the user presses "+", a vari‐
able is incremented. If "p" is pressed, several returns are sent
to the process, perhaps to poke it in some way, and "i" lets the
user interact with the process, effectively stealing away control
from the script. In each case, the exp_continue allows the cur‐
rent expect to continue pattern matching after executing the cur‐
rent action.
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
}
By default, exp_continue resets the timeout timer. The timer is
not restarted, if exp_continue is called with the -continue_timer
flag.
expect_after [expect_args]
works identically to the expect_before except that if patterns
from both expect and expect_after can match, the expect pattern
is used. See the expect_before command for more information.
expect_background [expect_args]
takes the same arguments as expect, however it returns immedi‐
ately. Patterns are tested whenever new input arrives. The pat‐
tern timeout and default are meaningless to expect_background and
are silently discarded. Otherwise, the expect_background command
uses expect_before and expect_after patterns just like expect
does.
When expect_background actions are being evaluated, background
processing for the same spawn id is blocked. Background process‐
ing is unblocked when the action completes. While background
processing is blocked, it is possible to do a (foreground) expect
on the same spawn id.
It is not possible to execute an expect while an expect_back‐
ground is unblocked. expect_background for a particular spawn id
is deleted by declaring a new expect_background with the same
spawn id. Declaring expect_background with no pattern removes
the given spawn id from the ability to match patterns in the
background.
expect_before [expect_args]
takes the same arguments as expect, however it returns immedi‐
ately. Pattern-action pairs from the most recent expect_before
with the same spawn id are implicitly added to any following ex‐
pect commands. If a pattern matches, it is treated as if it had
been specified in the expect command itself, and the associated
body is executed in the context of the expect command. If pat‐
terns from both expect_before and expect can match, the ex‐
pect_before pattern is used.
If no pattern is specified, the spawn id is not checked for any
patterns.
Unless overridden by a -i flag, expect_before patterns match
against the spawn id defined at the time that the expect_before
command was executed (not when its pattern is matched).
The -info flag causes expect_before to return the current speci‐
fications of what patterns it will match. By default, it reports
on the current spawn id. An optional spawn id specification may
be given for information on that spawn id. For example
expect_before -info -i $proc
At most one spawn id specification may be given. The flag -indi‐
rect suppresses direct spawn ids that come only from indirect
specifications.
Instead of a spawn id specification, the flag "-all" will cause
"-info" to report on all spawn ids.
The output of the -info flag can be reused as the argument to ex‐
pect_before.
expect_tty [expect_args]
is like expect but it reads characters from /dev/tty (i.e. key‐
strokes from the user). By default, reading is performed in
cooked mode. Thus, lines must end with a return in order for ex‐
pect to see them. This may be changed via stty (see the stty
command below).
expect_user [expect_args]
is like expect but it reads characters from stdin (i.e. key‐
strokes from the user). By default, reading is performed in
cooked mode. Thus, lines must end with a return in order for ex‐
pect to see them. This may be changed via stty (see the stty
command below).
fork creates a new process. The new process is an exact copy of the
current Expect process. On success, fork returns 0 to the new
(child) process and returns the process ID of the child process
to the parent process. On failure (invariably due to lack of re‐
sources, e.g., swap space, memory), fork returns -1 to the parent
process, and no child process is created.
Forked processes exit via the exit command, just like the origi‐
nal process. Forked processes are allowed to write to the log
files. If you do not disable debugging or logging in most of the
processes, the result can be confusing.
Some pty implementations may be confused by multiple readers and
writers, even momentarily. Thus, it is safest to fork before
spawning processes.
interact [string1 body1] ... [stringn [bodyn]]
gives control of the current process to the user, so that key‐
strokes are sent to the current process, and the stdout and
stderr of the current process are returned.
String-body pairs may be specified as arguments, in which case
the body is executed when the corresponding string is entered.
(By default, the string is not sent to the current process.)
The interpreter command is assumed, if the final body is missing.
If the arguments to the entire interact statement require more
than one line, all the arguments may be "braced" into one so as
to avoid terminating each line with a backslash. In this one
case, the usual Tcl substitutions will occur despite the braces.
For example, the following command runs interact with the follow‐
ing string-body pairs defined: When ^Z is pressed, Expect is
suspended. (The -reset flag restores the terminal modes.) When
^A is pressed, the user sees "you typed a control-A" and the
process is sent a ^A. When $ is pressed, the user sees the date.
When ^C is pressed, Expect exits. If "foo" is entered, the user
sees "bar". When ~~ is pressed, the Expect interpreter runs in‐
teractively.
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 [clock format [clock seconds]]."}
\003 exit
foo {send_user "bar"}
~~
}
In string-body pairs, strings are matched in the order they are
listed as arguments. Strings that partially match are not sent
to the current process in anticipation of the remainder coming.
If characters are then entered such that there can no longer pos‐
sibly be a match, only the part of the string will be sent to the
process that cannot possibly begin another match. Thus, strings
that are substrings of partial matches can match later, if the
original strings that was attempting to be match ultimately
fails.
By default, string matching is exact with no wild cards. (In
contrast, the expect command uses glob-style patterns by de‐
fault.) The -ex flag may be used to protect patterns that might
otherwise match interact flags from doing so. Any pattern begin‐
ning with a "-" should be protected this way. (All strings
starting with "-" are reserved for future options.)
The -re flag forces the string to be interpreted as a regexp-
style pattern. In this case, matching substrings are stored in
the variable interact_out similarly to the way expect stores its
output in the variable expect_out. The -indices flag is simi‐
larly supported.
The pattern eof introduces an action that is executed upon end-
of-file. A separate eof pattern may also follow the -output flag
in which case it is matched if an eof is detected while writing
output. The default eof action is "return", so that interact
simply returns upon any EOF.
The pattern timeout introduces a timeout (in seconds) and action
that is executed after no characters have been read for a given
time. The timeout pattern applies to the most recently specified
process. There is no default timeout. The special variable
"timeout" (used by the expect command) has no affect on this
timeout.
For example, the following statement could be used to autologout
users who have not typed anything for an hour but who still get
frequent system messages:
interact -input $user_spawn_id timeout 3600 return -output \
$spawn_id
If the pattern is the keyword null, and nulls are allowed (via
the remove_nulls command), the corresponding body is executed if
a single ASCII 0 is matched. It is not possible to match 0 bytes
via glob or regexp patterns.
Prefacing a pattern with the flag -iwrite causes the variable in‐
teract_out(spawn_id) to be set to the spawn_id which matched the
pattern (or eof).
Actions such as break and continue cause control structures
(i.e., for, proc) to behave in the usual way. However return
causes interact to return to its caller, while inter_return
causes interact to cause a return in its caller. For example, if
"proc foo" called interact which then executed the action in‐
ter_return, proc foo would return. (This means that if interact
calls interpreter interactively typing return will cause the in‐
teract to continue, while inter_return will cause the interact to
return to its caller.)
During interact, raw mode is used so that all characters may be
passed to the current process. If the current process does not
catch job control signals, it will stop if sent a stop signal (by
default ^Z). To restart it, send a continue signal (such as by
"kill -CONT <pid>"). If you really want to send a SIGSTOP to
such a process (by ^Z), consider spawning csh first and then run‐
ning your program. On the other hand, if you want to send a
SIGSTOP to Expect itself, first call interpreter (perhaps by us‐
ing an escape character), and then press ^Z.
String-body pairs can be used as a shorthand for avoiding having
to enter the interpreter and execute commands interactively. The
previous terminal mode is used while the body of a string-body
pair is being executed.
For speed, actions execute in raw mode by default. The -reset
flag resets the terminal to the mode it had before interact was
executed (invariably, cooked mode). Note that characters entered
when the mode is being switched may be lost (an unfortunate fea‐
ture of the terminal driver on some systems). The only reason to
use -reset is if your action depends on running in cooked mode.
The -echo flag sends characters that match the following pattern
back to the process that generated them as each character is
read. This may be useful when the user needs to see feedback
from partially typed patterns.
If a pattern is being echoed but eventually fails to match, the
characters are sent to the spawned process. If the spawned
process then echoes them, the user will see the characters twice.
-echo is probably only appropriate in situations where the user
is unlikely to not complete the pattern. For example, the fol‐
lowing excerpt is from rftp, the recursive-ftp script, where the
user is prompted to enter ~g, ~p, or ~l, to get, put, or list the
current directory recursively. These are so far away from the
normal ftp commands, that the user is unlikely to type ~ followed
by anything else, except mistakenly, in which case, they'll prob‐
ably just ignore the result anyway.
interact {
-echo ~g {getcurdirectory 1}
-echo ~l {getcurdirectory 0}
-echo ~p {putcurdirectory}
}
The -nobuffer flag sends characters that match the following pat‐
tern on to the output process as characters are read.
This is useful when you wish to let a program echo back the pat‐
tern. For example, the following might be used to monitor where
a person is dialing (a Hayes-style modem). Each time "atd" is
seen the script logs the rest of the line.
proc lognumber {} {
interact -nobuffer -re "(.*)\r" return
puts $log "[clock format [clock seconds]]: dialed $interact_out(1,string)"
}
interact -nobuffer "atd" lognumber
During interact, previous use of log_user is ignored. In partic‐
ular, interact will force its output to be logged (sent to the
standard output) since it is presumed the user doesn't wish to
interact blindly.
The -o flag causes any following key-body pairs to be applied to
the output of the current process. This can be useful, for exam‐
ple, when dealing with hosts that send unwanted characters during
a telnet session.
By default, interact expects the user to be writing stdin and
reading stdout of the Expect process itself. The -u flag (for
"user") makes interact look for the user as the process named by
its argument (which must be a spawned id).
This allows two unrelated processes to be joined together without
using an explicit loop. To aid in debugging, Expect diagnostics
always go to stderr (or stdout for certain logging and debugging
information). For the same reason, the interpreter command will
read interactively from stdin.
For example, the following fragment creates a login process.
Then it dials the user (not shown), and finally connects the two
together. Of course, any process may be substituted for login.
A shell, for example, would allow the user to work without sup‐
plying an account and password.
spawn login
set login $spawn_id
spawn tip modem
# dial back out to user
# connect user to login
interact -u $login
To send output to multiple processes, list each spawn id list
prefaced by a -output flag. Input for a group of output spawn
ids may be determined by a spawn id list prefaced by a -input
flag. (Both -input and -output may take lists in the same form
as the -i flag in the expect command, except that any_spawn_id is
not meaningful in interact.) All following flags and strings (or
patterns) apply to this input until another -input flag appears.
If no -input appears, -output implies "-input $user_spawn_id
-output". (Similarly, with patterns that do not have -input.)
If one -input is specified, it overrides $user_spawn_id. If a
second -input is specified, it overrides $spawn_id. Additional
-input flags may be specified.
The two implied input processes default to having their outputs
specified as $spawn_id and $user_spawn_id (in reverse). If a
-input flag appears with no -output flag, characters from that
process are discarded.
The -i flag introduces a replacement for the current spawn_id
when no other -input or -output flags are used. A -i flag im‐
plies a -o flag.
It is possible to change the processes that are being interacted
with by using indirect spawn ids. (Indirect spawn ids are de‐
scribed in the section on the expect command.) Indirect spawn
ids may be specified with the -i, -u, -input, or -output flags.
interpreter [args]
causes the user to be interactively prompted for Expect and Tcl
commands. The result of each command is printed.
Actions such as break and continue cause control structures
(i.e., for, proc) to behave in the usual way. However return
causes interpreter to return to its caller, while inter_return
causes interpreter to cause a return in its caller. For example,
if "proc foo" called interpreter which then executed the action
inter_return, proc foo would return. Any other command causes
interpreter to continue prompting for new commands.
By default, the prompt contains two integers. The first integer
describes the depth of the evaluation stack (i.e., how many times
Tcl_Eval has been called). The second integer is the Tcl history
identifier. The prompt can be set by defining a procedure called
"prompt1" whose return value becomes the next prompt. If a
statement has open quotes, parens, braces, or brackets, a sec‐
ondary prompt (by default "+> ") is issued upon newline. The
secondary prompt may be set by defining a procedure called
"prompt2".
During interpreter, cooked mode is used, even if the its caller
was using raw mode.
If stdin is closed, interpreter will return unless the -eof flag
is used, in which case the subsequent argument is invoked.
log_file [args] [[-a] file]
If a filename is provided, log_file will record a transcript of
the session (beginning at that point) in the file. log_file will
stop recording if no argument is given. Any previous log file is
closed.
Instead of a filename, a Tcl file identifier may be provided by
using the -open or -leaveopen flags. This is similar to the
spawn command. (See spawn for more info.)
The -a flag forces output to be logged that was suppressed by the
log_user command.
By default, the log_file command appends to old files rather than
truncating them, for the convenience of being able to turn log‐
ging off and on multiple times in one session. To truncate
files, use the -noappend flag.
The -info flag causes log_file to return a description of the
most recent non-info arguments given.
log_user -info|0|1
By default, the send/expect dialogue is logged to stdout (and a
logfile if open). The logging to stdout is disabled by the com‐
mand "log_user 0" and reenabled by "log_user 1". Logging to the
logfile is unchanged.
The -info flag causes log_user to return a description of the
most recent non-info arguments given.
match_max [-d] [-i spawn_id] [size]
defines the size of the buffer (in bytes) used internally by ex‐
pect. With no size argument, the current size is returned.
With the -d flag, the default size is set. (The initial default
is 2000.) With the -i flag, the size is set for the named spawn
id, otherwise it is set for the current process.
overlay [-# spawn_id] [-# spawn_id] [...] program [args]
executes program args in place of the current Expect program,
which terminates. A bare hyphen argument forces a hyphen in
front of the command name as if it was a login shell. All
spawn_ids are closed except for those named as arguments. These
are mapped onto the named file identifiers.
Spawn_ids are mapped to file identifiers for the new program to
inherit. For example, the following line runs chess and allows
it to be controlled by the current process - say, a chess master.
overlay -0 $spawn_id -1 $spawn_id -2 $spawn_id chess
This is more efficient than "interact -u", however, it sacrifices
the ability to do programmed interaction since the Expect process
is no longer in control.
Note that no controlling terminal is provided. Thus, if you dis‐
connect or remap standard input, programs that do job control
(shells, login, etc) will not function properly.
parity [-d] [-i spawn_id] [value]
defines whether parity should be retained or stripped from the
output of spawned processes. If value is zero, parity is
stripped, otherwise it is not stripped. With no value argument,
the current value is returned.
With the -d flag, the default parity value is set. (The initial
default is 1, i.e., parity is not stripped.) With the -i flag,
the parity value is set for the named spawn id, otherwise it is
set for the current process.
remove_nulls [-d] [-i spawn_id] [value]
defines whether nulls are retained or removed from the output of
spawned processes before pattern matching or storing in the vari‐
able expect_out or interact_out. If value is 1, nulls are re‐
moved. If value is 0, nulls are not removed. With no value ar‐
gument, the current value is returned.
With the -d flag, the default value is set. (The initial default
is 1, i.e., nulls are removed.) With the -i flag, the value is
set for the named spawn id, otherwise it is set for the current
process.
Whether or not nulls are removed, Expect will record null bytes
to the log and stdout.
send [-flags] string
Sends string to the current process. For example, the command
send "hello world\r"
sends the characters, h e l l o <blank> w o r l d <return> to the
current process. (Tcl includes a printf-like command (called
format) which can build arbitrarily complex strings.)
Characters are sent immediately although programs with line-
buffered input will not read the characters until a return char‐
acter is sent. A return character is denoted "\r".
The -- flag forces the next argument to be interpreted as a
string rather than a flag. Any string can be preceded by "--"
whether or not it actually looks like a flag. This provides a
reliable mechanism to specify variable strings without being
tripped up by those that accidentally look like flags. (All
strings starting with "-" are reserved for future options.)
The -i flag declares that the string be sent to the named
spawn_id. If the spawn_id is user_spawn_id, and the terminal is
in raw mode, newlines in the string are translated to return-new‐
line sequences so that they appear as if the terminal was in
cooked mode. The -raw flag disables this translation.
The -null flag sends null characters (0 bytes). By default, one
null is sent. An integer may follow the -null to indicate how
many nulls to send.
The -break flag generates a break condition. This only makes
sense if the spawn id refers to a tty device opened via "spawn
-open". If you have spawned a process such as tip, you should
use tip's convention for generating a break.
The -s flag forces output to be sent "slowly", thus avoid the
common situation where a computer outtypes an input buffer that
was designed for a human who would never outtype the same buffer.
This output is controlled by the value of the variable
"send_slow" which takes a two element list. The first element is
an integer that describes the number of bytes to send atomically.
The second element is a real number that describes the number of
seconds by which the atomic sends must be separated. For exam‐
ple, "set send_slow {10 .001}" would force "send -s" to send
strings with 1 millisecond in between each 10 characters sent.
The -h flag forces output to be sent (somewhat) like a human ac‐
tually typing. Human-like delays appear between the characters.
(The algorithm is based upon a Weibull distribution, with modifi‐
cations to suit this particular application.) This output is
controlled by the value of the variable "send_human" which takes
a five element list. The first two elements are average interar‐
rival time of characters in seconds. The first is used by de‐
fault. The second is used at word endings, to simulate the sub‐
tle pauses that occasionally occur at such transitions. The
third parameter is a measure of variability where .1 is quite
variable, 1 is reasonably variable, and 10 is quite invariable.
The extremes are 0 to infinity. The last two parameters are, re‐
spectively, a minimum and maximum interarrival time. The minimum
and maximum are used last and "clip" the final time. The ulti‐
mate average can be quite different from the given average if the
minimum and maximum clip enough values.
As an example, the following command emulates a fast and consis‐
tent typist:
set send_human {.1 .3 1 .05 2}
send -h "I'm hungry. Let's do lunch."
while the following might be more suitable after a hangover:
set send_human {.4 .4 .2 .5 100}
send -h "Goodd party lash night!"
Note that errors are not simulated, although you can set up error
correction situations yourself by embedding mistakes and correc‐
tions in a send argument.
The flags for sending null characters, for sending breaks, for
forcing slow output and for human-style output are mutually ex‐
clusive. Only the one specified last will be used. Furthermore,
no string argument can be specified with the flags for sending
null characters or breaks.
It is a good idea to precede the first send to a process by an
expect. expect will wait for the process to start, while send
cannot. In particular, if the first send completes before the
process starts running, you run the risk of having your data ig‐
nored. In situations where interactive programs offer no initial
prompt, you can precede send by a delay as in:
# To avoid giving hackers hints on how to break in,
# this system does not prompt for an external password.
# Wait for 5 seconds for exec to complete
spawn telnet very.secure.gov
sleep 5
send password\r
exp_send is an alias for send. If you are using Expectk or some
other variant of Expect in the Tk environment, send is defined by
Tk for an entirely different purpose. exp_send is provided for
compatibility between environments. Similar aliases are provided
for other Expect's other send commands.
send_error [-flags] string
is like send, except that the output is sent to stderr rather
than the current process.
send_log [--] string
is like send, except that the string is only sent to the log file
(see log_file.) The arguments are ignored if no log file is
open.
send_tty [-flags] string
is like send, except that the output is sent to /dev/tty rather
than the current process.
send_user [-flags] string
is like send, except that the output is sent to stdout rather
than the current process.
sleep seconds
causes the script to sleep for the given number of seconds. Sec‐
onds may be a decimal number. Interrupts (and Tk events if you
are using Expectk) are processed while Expect sleeps.
spawn [args] program [args]
creates a new process running program args. Its stdin, stdout
and stderr are connected to Expect, so that they may be read and
written by other Expect commands. The connection is broken by
close or if the process itself closes any of the file identi‐
fiers.
When a process is started by spawn, the variable spawn_id is set
to a descriptor referring to that process. The process described
by spawn_id is considered the current process. spawn_id may be
read or written, in effect providing job control.
user_spawn_id is a global variable containing a descriptor which
refers to the user. For example, when spawn_id is set to this
value, expect behaves like expect_user.
error_spawn_id is a global variable containing a descriptor which
refers to the standard error. For example, when spawn_id is set
to this value, send behaves like send_error.
tty_spawn_id is a global variable containing a descriptor which
refers to /dev/tty. If /dev/tty does not exist (such as in a
cron, at, or batch script), then tty_spawn_id is not defined.
This may be tested as:
if {[info vars tty_spawn_id]} {
# /dev/tty exists
} else {
# /dev/tty doesn't exist
# probably in cron, batch, or at script
}
spawn returns the UNIX process id. If no process is spawned, 0
is returned. The variable spawn_out(slave,name) is set to the
name of the pty slave device.
By default, spawn echoes the command name and arguments. The
-noecho flag stops spawn from doing this.
The -console flag causes console output to be redirected to the
spawned process. This is not supported on all systems.
Internally, spawn uses a pty, initialized the same way as the
user's tty. This is further initialized so that all settings are
"sane" (according to stty(1)). If the variable stty_init is de‐
fined, it is interpreted in the style of stty arguments as fur‐
ther configuration. For example, "set stty_init raw" will cause
further spawned processes's terminals to start in raw mode.
-nottycopy skips the initialization based on the user's tty.
-nottyinit skips the "sane" initialization.
Normally, spawn takes little time to execute. If you notice
spawn taking a significant amount of time, it is probably encoun‐
tering ptys that are wedged. A number of tests are run on ptys
to avoid entanglements with errant processes. (These take 10
seconds per wedged pty.) Running Expect with the -d option will
show if Expect is encountering many ptys in odd states. If you
cannot kill the processes to which these ptys are attached, your
only recourse may be to reboot.
If program cannot be spawned successfully because exec(2) fails
(e.g. when program doesn't exist), an error message will be re‐
turned by the next interact or expect command as if program had
run and produced the error message as output. This behavior is a
natural consequence of the implementation of spawn. Internally,
spawn forks, after which the spawned process has no way to commu‐
nicate with the original Expect process except by communication
via the spawn_id.
The -open flag causes the next argument to be interpreted as a
Tcl file identifier (i.e., returned by open.) The spawn id can
then be used as if it were a spawned process. (The file identi‐
fier should no longer be used.) This lets you treat raw devices,
files, and pipelines as spawned processes without using a pty. 0
is returned to indicate there is no associated process. When the
connection to the spawned process is closed, so is the Tcl file
identifier. The -leaveopen flag is similar to -open except that
-leaveopen causes the file identifier to be left open even after
the spawn id is closed.
The -pty flag causes a pty to be opened but no process spawned.
0 is returned to indicate there is no associated process.
Spawn_id is set as usual.
The variable spawn_out(slave,fd) is set to a file identifier cor‐
responding to the pty slave. It can be closed using "close
-slave".
The -ignore flag names a signal to be ignored in the spawned
process. Otherwise, signals get the default behavior. Signals
are named as in the trap command, except that each signal re‐
quires a separate flag.
strace level
causes following statements to be printed before being executed.
(Tcl's trace command traces variables.) level indicates how far
down in the call stack to trace. For example, the following com‐
mand runs Expect while tracing the first 4 levels of calls, but
none below that.
expect -c "strace 4" script.exp
The -info flag causes strace to return a description of the most
recent non-info arguments given.
stty args
changes terminal modes similarly to the external stty command.
By default, the controlling terminal is accessed. Other termi‐
nals can be accessed by appending "< /dev/tty..." to the command.
(Note that the arguments should not be grouped into a single ar‐
gument.)
Requests for status return it as the result of the command. If
no status is requested and the controlling terminal is accessed,
the previous status of the raw and echo attributes are returned
in a form which can later be used by the command.
For example, the arguments raw or -cooked put the terminal into
raw mode. The arguments -raw or cooked put the terminal into
cooked mode. The arguments echo and -echo put the terminal into
echo and noecho mode respectively.
The following example illustrates how to temporarily disable
echoing. This could be used in otherwise-automatic scripts to
avoid embedding passwords in them. (See more discussion on this
under EXPECT HINTS below.)
stty -echo
send_user "Password: "
expect_user -re "(.*)\n"
set password $expect_out(1,string)
stty echo
system args
gives args to sh(1) as input, just as if it had been typed as a
command from a terminal. Expect waits until the shell termi‐
nates. The return status from sh is handled the same way that
exec handles its return status.
In contrast to exec which redirects stdin and stdout to the
script, system performs no redirection (other than that indicated
by the string itself). Thus, it is possible to use programs
which must talk directly to /dev/tty. For the same reason, the
results of system are not recorded in the log.
timestamp [args]
returns a timestamp. With no arguments, the number of seconds
since the epoch is returned.
The -format flag introduces a string which is returned but with
substitutions made according to the POSIX rules for strftime.
For example %a is replaced by an abbreviated weekday name (i.e.,
Sat). Others are:
%a abbreviated weekday name
%A full weekday name
%b abbreviated month name
%B full month name
%c date-time as in: Wed Oct 6 11:45:56 1993
%d day of the month (01-31)
%H hour (00-23)
%I hour (01-12)
%j day (001-366)
%m month (01-12)
%M minute (00-59)
%p am or pm
%S second (00-61)
%u day (1-7, Monday is first day of week)
%U week (00-53, first Sunday is first day of week one)
%V week (01-53, ISO 8601 style)
%w day (0-6)
%W week (00-53, first Monday is first day of week one)
%x date-time as in: Wed Oct 6 1993
%X time as in: 23:59:59
%y year (00-99)
%Y year as in: 1993
%Z timezone (or nothing if not determinable)
%% a bare percent sign
Other % specifications are undefined. Other characters will be
passed through untouched. Only the C locale is supported.
The -seconds flag introduces a number of seconds since the epoch
to be used as a source from which to format. Otherwise, the cur‐
rent time is used.
The -gmt flag forces timestamp output to use the GMT timezone.
With no flag, the local timezone is used.
trap [[command] signals]
causes the given command to be executed upon future receipt of
any of the given signals. The command is executed in the global
scope. If command is absent, the signal action is returned. If
command is the string SIG_IGN, the signals are ignored. If com‐
mand is the string SIG_DFL, the signals are result to the system
default. signals is either a single signal or a list of signals.
Signals may be specified numerically or symbolically as per sig‐
nal(3). The "SIG" prefix may be omitted.
With no arguments (or the argument -number), trap returns the
signal number of the trap command currently being executed.
The -code flag uses the return code of the command in place of
whatever code Tcl was about to return when the command originally
started running.
The -interp flag causes the command to be evaluated using the in‐
terpreter active at the time the command started running rather
than when the trap was declared.
The -name flag causes the trap command to return the signal name
of the trap command currently being executed.
The -max flag causes the trap command to return the largest sig‐
nal number that can be set.
For example, the command "trap {send_user "Ouch!"} SIGINT" will
print "Ouch!" each time the user presses ^C.
By default, SIGINT (which can usually be generated by pressing
^C) and SIGTERM cause Expect to exit. This is due to the follow‐
ing trap, created by default when Expect starts.
trap exit {SIGINT SIGTERM}
If you use the -D flag to start the debugger, SIGINT is redefined
to start the interactive debugger. This is due to the following
trap:
trap {exp_debug 1} SIGINT
The debugger trap can be changed by setting the environment vari‐
able EXPECT_DEBUG_INIT to a new trap command.
You can, of course, override both of these just by adding trap
commands to your script. In particular, if you have your own
"trap exit SIGINT", this will override the debugger trap. This
is useful if you want to prevent users from getting to the debug‐
ger at all.
If you want to define your own trap on SIGINT but still trap to
the debugger when it is running, use:
if {![exp_debug]} {trap mystuff SIGINT}
Alternatively, you can trap to the debugger using some other sig‐
nal.
trap will not let you override the action for SIGALRM as this is
used internally to Expect. The disconnect command sets SIGALRM
to SIG_IGN (ignore). You can reenable this as long as you dis‐
able it during subsequent spawn commands.
See signal(3) for more info.
wait [args]
delays until a spawned process (or the current process if none is
named) terminates.
wait normally returns a list of four integers. The first integer
is the pid of the process that was waited upon. The second inte‐
ger is the corresponding spawn id. The third integer is -1 if an
operating system error occurred, or 0 otherwise. If the third
integer was 0, the fourth integer is the status returned by the
spawned process. If the third integer was -1, the fourth integer
is the value of errno set by the operating system. The global
variable errorCode is also set.
Additional elements may appear at the end of the return value
from wait. An optional fifth element identifies a class of in‐
formation. Currently, the only possible value for this element
is CHILDKILLED in which case the next two values are the C-style
signal name and a short textual description.
The -i flag declares the process to wait corresponding to the
named spawn_id (NOT the process id). Inside a SIGCHLD handler,
it is possible to wait for any spawned process by using the spawn
id -1.
The -nowait flag causes the wait to return immediately with the
indication of a successful wait. When the process exits (later),
it will automatically disappear without the need for an explicit
wait.
The wait command may also be used wait for a forked process using
the arguments "-i -1". Unlike its use with spawned processes,
this command can be executed at any time. There is no control
over which process is reaped. However, the return value can be
checked for the process id.
LIBRARIES
Expect automatically knows about two built-in libraries for Expect
scripts. These are defined by the directories named in the variables
exp_library and exp_exec_library. Both are meant to contain utility
files that can be used by other scripts.
exp_library contains architecture-independent files. exp_exec_library
contains architecture-dependent files. Depending on your system, both
directories may be totally empty. The existence of the file
$exp_exec_library/cat-buffers describes whether your /bin/cat buffers
by default.
PRETTY-PRINTING
A vgrind definition is available for pretty-printing Expect scripts.
Assuming the vgrind definition supplied with the Expect distribution is
correctly installed, you can use it as:
vgrind -lexpect file
EXAMPLES
It many not be apparent how to put everything together that the man
page describes. I encourage you to read and try out the examples in
the example directory of the Expect distribution. Some of them are
real programs. Others are simply illustrative of certain techniques,
and of course, a couple are just quick hacks. The INSTALL file has a
quick overview of these programs.
The Expect papers (see SEE ALSO) are also useful. While some papers
use syntax corresponding to earlier versions of Expect, the accompany‐
ing rationales are still valid and go into a lot more detail than this
man page.
CAVEATS
Extensions may collide with Expect's command names. For example, send
is defined by Tk for an entirely different purpose. For this reason,
most of the Expect commands are also available as "exp_XXXX". Commands
and variables beginning with "exp", "inter", "spawn", and "timeout" do
not have aliases. Use the extended command names if you need this com‐
patibility between environments.
Expect takes a rather liberal view of scoping. In particular, vari‐
ables read by commands specific to the Expect program will be sought
first from the local scope, and if not found, in the global scope. For
example, this obviates the need to place "global timeout" in every pro‐
cedure you write that uses expect. On the other hand, variables writ‐
ten are always in the local scope (unless a "global" command has been
issued). The most common problem this causes is when spawn is executed
in a procedure. Outside the procedure, spawn_id no longer exists, so
the spawned process is no longer accessible simply because of scoping.
Add a "global spawn_id" to such a procedure.
If you cannot enable the multispawning capability (i.e., your system
supports neither select (BSD *.*), poll (SVR>2), nor something equiva‐
lent), Expect will only be able to control a single process at a time.
In this case, do not attempt to set spawn_id, nor should you execute
processes via exec while a spawned process is running. Furthermore,
you will not be able to expect from multiple processes (including the
user as one) at the same time.
Terminal parameters can have a big effect on scripts. For example, if
a script is written to look for echoing, it will misbehave if echoing
is turned off. For this reason, Expect forces sane terminal parameters
by default. Unfortunately, this can make things unpleasant for other
programs. As an example, the emacs shell wants to change the "usual"
mappings: newlines get mapped to newlines instead of carriage-return
newlines, and echoing is disabled. This allows one to use emacs to
edit the input line. Unfortunately, Expect cannot possibly guess this.
You can request that Expect not override its default setting of termi‐
nal parameters, but you must then be very careful when writing scripts
for such environments. In the case of emacs, avoid depending upon
things like echoing and end-of-line mappings.
The commands that accepted arguments braced into a single list (the ex‐
pect variants and interact) use a heuristic to decide if the list is
actually one argument or many. The heuristic can fail only in the case
when the list actually does represent a single argument which has mul‐
tiple embedded \n's with non-whitespace characters between them. This
seems sufficiently improbable, however the argument "-nobrace" can be
used to force a single argument to be handled as a single argument.
This could conceivably be used with machine-generated Expect code.
Similarly, -brace forces a single argument to be handle as multiple
patterns/actions.
BUGS
It was really tempting to name the program "sex" (for either "Smart
EXec" or "Send-EXpect"), but good sense (or perhaps just Puritanism)
prevailed.
On some systems, when a shell is spawned, it complains about not being
able to access the tty but runs anyway. This means your system has a
mechanism for gaining the controlling tty that Expect doesn't know
about. Please find out what it is, and send this information back to
me.
Ultrix 4.1 (at least the latest versions around here) considers time‐
outs of above 1000000 to be equivalent to 0.
Digital UNIX 4.0A (and probably other versions) refuses to allocate
ptys if you define a SIGCHLD handler. See grantpt page for more info.
IRIX 6.0 does not handle pty permissions correctly so that if Expect
attempts to allocate a pty previously used by someone else, it fails.
Upgrade to IRIX 6.1.
Telnet (verified only under SunOS 4.1.2) hangs if TERM is not set.
This is a problem under cron, at and in cgi scripts, which do not de‐
fine TERM. Thus, you must set it explicitly - to what type is usually
irrelevant. It just has to be set to something! The following proba‐
bly suffices for most cases.
set env(TERM) vt100
Tip (verified only under BSDI BSD/OS 3.1 i386) hangs if SHELL and HOME
are not set. This is a problem under cron, at and in cgi scripts,
which do not define these environment variables. Thus, you must set
them explicitly - to what type is usually irrelevant. It just has to
be set to something! The following probably suffices for most cases.
set env(SHELL) /bin/sh
set env(HOME) /usr/local/bin
Some implementations of ptys are designed so that the kernel throws
away any unread output after 10 to 15 seconds (actual number is imple‐
mentation-dependent) after the process has closed the file descriptor.
Thus Expect programs such as
spawn date
sleep 20
expect
will fail. To avoid this, invoke non-interactive programs with exec
rather than spawn. While such situations are conceivable, in practice
I have never encountered a situation in which the final output of a
truly interactive program would be lost due to this behavior.
On the other hand, Cray UNICOS ptys throw away any unread output imme‐
diately after the process has closed the file descriptor. I have re‐
ported this to Cray and they are working on a fix.
Sometimes a delay is required between a prompt and a response, such as
when a tty interface is changing UART settings or matching baud rates
by looking for start/stop bits. Usually, all this is require is to
sleep for a second or two. A more robust technique is to retry until
the hardware is ready to receive input. The following example uses
both strategies:
send "speed 9600\r";
sleep 1
expect {
timeout {send "\r"; exp_continue}
$prompt
}
trap -code will not work with any command that sits in Tcl's event
loop, such as sleep. The problem is that in the event loop, Tcl dis‐
cards the return codes from async event handlers. A workaround is to
set a flag in the trap code. Then check the flag immediately after the
command (i.e., sleep).
The expect_background command ignores -timeout arguments and has no
concept of timeouts in general.
EXPECT HINTS
There are a couple of things about Expect that may be non-intuitive.
This section attempts to address some of these things with a couple of
suggestions.
A common expect problem is how to recognize shell prompts. Since these
are customized differently by differently people and different shells,
portably automating rlogin can be difficult without knowing the prompt.
A reasonable convention is to have users store a regular expression de‐
scribing their prompt (in particular, the end of it) in the environment
variable EXPECT_PROMPT. Code like the following can be used. If EX‐
PECT_PROMPT doesn't exist, the code still has a good chance of func‐
tioning correctly.
set prompt "(%|#|\\$) $" ;# default prompt
catch {set prompt $env(EXPECT_PROMPT)}
expect -re $prompt
I encourage you to write expect patterns that include the end of what‐
ever you expect to see. This avoids the possibility of answering a
question before seeing the entire thing. In addition, while you may
well be able to answer questions before seeing them entirely, if you
answer early, your answer may appear echoed back in the middle of the
question. In other words, the resulting dialogue will be correct but
look scrambled.
Most prompts include a space character at the end. For example, the
prompt from ftp is 'f', 't', 'p', '>' and <blank>. To match this
prompt, you must account for each of these characters. It is a common
mistake not to include the blank. Put the blank in explicitly.
If you use a pattern of the form X*, the * will match all the output
received from the end of X to the last thing received. This sounds in‐
tuitive but can be somewhat confusing because the phrase "last thing
received" can vary depending upon the speed of the computer and the
processing of I/O both by the kernel and the device driver.
In particular, humans tend to see program output arriving in huge
chunks (atomically) when in reality most programs produce output one
line at a time. Assuming this is the case, the * in the pattern of the
previous paragraph may only match the end of the current line even
though there seems to be more, because at the time of the match that
was all the output that had been received.
expect has no way of knowing that further output is coming unless your
pattern specifically accounts for it.
Even depending on line-oriented buffering is unwise. Not only do pro‐
grams rarely make promises about the type of buffering they do, but
system indigestion can break output lines up so that lines break at
seemingly random places. Thus, if you can express the last few charac‐
ters of a prompt when writing patterns, it is wise to do so.
If you are waiting for a pattern in the last output of a program and
the program emits something else instead, you will not be able to de‐
tect that with the timeout keyword. The reason is that expect will not
timeout - instead it will get an eof indication. Use that instead.
Even better, use both. That way if that line is ever moved around, you
won't have to edit the line itself.
Newlines are usually converted to carriage return, linefeed sequences
when output by the terminal driver. Thus, if you want a pattern that
explicitly matches the two lines, from, say, printf("foo\nbar"), you
should use the pattern "foo\r\nbar".
A similar translation occurs when reading from the user, via ex‐
pect_user. In this case, when you press return, it will be translated
to a newline. If Expect then passes that to a program which sets its
terminal to raw mode (like telnet), there is going to be a problem, as
the program expects a true return. (Some programs are actually forgiv‐
ing in that they will automatically translate newlines to returns, but
most don't.) Unfortunately, there is no way to find out that a program
put its terminal into raw mode.
Rather than manually replacing newlines with returns, the solution is
to use the command "stty raw", which will stop the translation. Note,
however, that this means that you will no longer get the cooked line-
editing features.
interact implicitly sets your terminal to raw mode so this problem will
not arise then.
It is often useful to store passwords (or other private information) in
Expect scripts. This is not recommended since anything that is stored
on a computer is susceptible to being accessed by anyone. Thus, inter‐
actively prompting for passwords from a script is a smarter idea than
embedding them literally. Nonetheless, sometimes such embedding is the
only possibility.
Unfortunately, the UNIX file system has no direct way of creating
scripts which are executable but unreadable. Systems which support
setgid shell scripts may indirectly simulate this as follows:
Create the Expect script (that contains the secret data) as usual.
Make its permissions be 750 (-rwxr-x---) and owned by a trusted group,
i.e., a group which is allowed to read it. If necessary, create a new
group for this purpose. Next, create a /bin/sh script with permissions
2751 (-rwxr-s--x) owned by the same group as before.
The result is a script which may be executed (and read) by anyone.
When invoked, it runs the Expect script.
SEE ALSO
Tcl(3), libexpect(3)
"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Pro‐
grams" by Don Libes, pp. 602, ISBN 1-56592-090-2, O'Reilly and Asso‐
ciates, 1995.
"expect: Curing Those Uncontrollable Fits of Interactivity" by Don
Libes, Proceedings of the Summer 1990 USENIX Conference, Anaheim, Cali‐
fornia, June 11-15, 1990.
"Using expect to Automate System Administration Tasks" by Don Libes,
Proceedings of the 1990 USENIX Large Installation Systems Administra‐
tion 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 Jour‐
nals, 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 Sus‐
sex, 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.
AUTHOR
Don Libes, National Institute of Standards and Technology
ACKNOWLEDGMENTS
Thanks to John Ousterhout for Tcl, and Scott Paisley for inspiration.
Thanks to Rob Savoye for Expect's autoconfiguration code.
The HISTORY file documents much of the evolution of expect. It makes
interesting reading and might give you further insight to this soft‐
ware. Thanks to the people mentioned in it who sent me bug fixes and
gave other assistance.
Design and implementation of Expect was paid for in part by the U.S.
government and is therefore in the public domain. However the author
and NIST would like credit if this program and documentation or por‐
tions of them are used.
29 December 1994 EXPECT(1)