Provided by: manpages-ja_0.5.0.0.20221215+dfsg-1_all
名前
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"という名前は、uucpで有名になった send/expect の概念に由来する。 (kermitや他のモデ ム制御プログラムでも、この概念は使われている) しかし、uucp とは違って Expect は一般化され ているので、想像されるどんなプログラムやタスクに対しても マクロコマンド(user-level command)として機能できる。 Expect は、同時に複数のプログラムと会話することができる。 Expect にできることの例をいくつか挙げておく: • 電話代を払わずにログインできるようにコンピュータからあなたに電話を掛け直させ る。 • ゲーム(例えば rogue)を始める時に、最適なパラメタがもらえなかった場合 最適なパラ メタがもらえるまで何度でもリスタートを行ない、その後制御を人間に移す。 • fsckを走らせた時に現れる質問に、前もって決めておいた方針に従って、 "yes", "no", "手入力"を切替えて、返答する。 • 他のネットワークや BBS(例えばMCI Mail, CompuServe)に接続した時に 自動的にメール の取り込み、発信を行なう。 • 環境変数、カレントディレクトリ、その他の情報を、rlogin, telnet, tip, su, chgrp などを行なった先へ持っていく。 これらの処理をシェルが行なえない理由はたくさんある (やってみればわかるだろう)。全部 Expect ならできる。 一般に Expect は、プログラムとユーザーのやりとりが必要なプログラムを走らせるときに 役に立 つ。大事なことは、このやりとりがプログラムの性格を持っていると いうことである。 Expect は、必要ならユーザーに制御を返すこともできる(しかも、プログラムは 中断されない)。同様 に、ユーザーは制御をいつでもスクリプトに返すことができる。
用法
Expect は、 cmdfile を読み込み、実行するコマンドのリストを得る。 Expect は、#! 表記をサ ポートする OS で、先頭行に #!/usr/local/bin/expect -f と書いておいて実行させることもできる。 もちろん、パスは正確に Expect のある場所を指示して いなければならない。 /usr/local/bin は、一例である。 -c フラグで、スクリプトを実行する前に、実行するコマンドを指示する。 コマンドはシェルに壊さ れないようにクオートしておくべきである。 このオプションは何回出てきても構わない。 複数コマ ンドを指示した場合は、セミコロンで連結されたコマンドのように 扱われる。 コマンドは現れた順 に実行される。(Expectk では、 -command と書く) -d フラグで、デバッグ情報出力を有効にする。基本的に 内部のコマンド(例えば expect や interact) の振舞いを報告する。 このフラグは"exp_internal 1"とスクリプトの先頭に書くのと同 じことだが、 さらに Expect のバージョン番号も出力される。 ( strace コマンドは、命令をト レースするのに便利である。 trace コマンドは、変数値をトレースするのに便利である。) (Expectk を使う時は、このオプションは -diag と書く。) -D フラグで対話型デバッガを有効にする。整数値が続かなければならない。 値が 0 でないか、C が押されると、次の Tcl 処理の前でデバッガに制御が移る。 ブレークポイントにかかった時や他の デバッグ命令を実行した時も、同じである。 デバッガについての情報がもっと欲しければ、 README や下記の関連項目を読むこと。 (Expectk を使っている時は、このオプションは -Debug) -f フラグで、コマンドを読んでくるファイルを指示する。このフラグは あってもなくても良いのだ が、#! 表記と一緒に使うと 引数からプログラム名を除けるから、その場合意味がある。 (Expectk では -file) デフォルトでは、コマンドファイルがメモリに一度に読み込まれ、そこで実行される。 一行ずつコ マンドファイルを読んだ方が望ましい場合もある。例えば、 標準入力はこのように扱った方が良 い。強制的にこのモードを指定するには、 -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) ではその引数が見えてしまう ことに注意 すること。 -N フラグを用いない限り、ファイル $exp_library/expect.rc が(あれば)自動的に 実行される。 (Expectk では、 -NORC) -n フラグ (Expectk では、 -norc) を用いない限り、 続いて、ファイル ~/.expect.rc が、自動的に実行される。 環境変数 DOTDIR が定義されていれば、そこが .expect.rc のあるディレクトリ として扱われる。 この二つのrcファイルの実行より先に -c フラグで指示されたコマンドが実行される。 -v フラグを指示すると、バージョン番号を表示して終了する。 (Expectkでは、-version) オプション args は、リストに変換されて、変数 argv に保存される。 argc は、argv のリスト 長(要素の数)に設定される。 argv0 は、スクリプト名に設定される(スクリプトを使っていなければ、 バイナリの名前になる)。 例えば、以下のスクリプトを実行すると、スクリプト名と最初の引数3つを表示する: 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"という 本(関連項目を参照)がベストである。 このマニュアルページはリファレンスとして書いているの で、 含まれている例は非常に限られている。注意すること。 このマニュアルページで、大文字の"E"で"Expect"とあれば、それは、 Expect プログラムを指 し、一方小文字の"e"で"expect"とあれば、それは、 Expect プログラムに実装されている expect コマンドを指す。注意すること。 close [-slave] [-onexec 0|1] [-i spawn_id] カレントプロセスへのコネクションをクローズする。 ほとんどの対話型プログラムが標準入 力の EOF を検出し exit する。 それゆえ、 close はそのプロセスを kill するのにも通常 充分である。 -i フラグを指示すると、続く spawn_id を持つプロセスをクローズする。 expect と interact は両方とも、カレントプロセスが exit した時点を検出して、明示しな くても close を実行する。 しかし、"exec kill $pid" などのように、あなたがプロセスを kill している なら、明示的に close を呼ぶ必要がある。 -onexec フラグを指示すると、新しい spawn が起きた時またはプロセスが重ねられた時に 前 の spawn を閉じるべきかどうかを指示することができる。 前の spawn id で開いたままにし ておきたければ、値 0 を用いる。 0 でない整数を指示すると、新しいプロセス中では前の spawn はクローズされる (デフォルト)。 -slave フラグを指示すると、その spawn id の抱えているスレーブの spawn もクローズす る。 ("spawn -pty"を参照) コネクションがクローズされると、スレーブはオープン状態で あっても クローズされる。 コネクションのクローズが明示されていたか否かに全然関わりなく、 関係するカーネルプロ セススロットをクリアしてしまいたければ、 wait を呼ぶこと。 close は、 wait を呼ばな い。プロセスへのコネクションをクローズすると、そのプロセスが exit するという保証がな いからである。 もっと知りたければ、 wait の項を参照すること。 debug [[-now] 0|1] は、Tcl デバッガを制御する。デバッガにより、ステップ実行、ブレークポイントの 設定な どが行なえる。 引数がない場合、デバッガが走っていれば 1 を、そうでなければ 0 を返す。 引数が 1 なら、デバッガが起動される。引数が 0 なら、デバッガが停止する。 引数 1 の前 に -now フラグがあれば、デバッガは即座に起動される(つまり、 debug コマンドそのものの 途中で)。そうでなければ、デバッガは次の Tcl コマンドから 起動される。 debug コマンドはトラップを変更しない。 -D フラグをつけて起動させた場合とはそこが違 う(上記参照)。 デバッガについては、README ファイルと関連項目を参照すること。 disconnect fork されたプロセスを端末から切り離す。バックグラウンドで動作は続く。 プロセスは可能 であれば自分自身のプロセスグループを与える。 標準入出力は、/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 が disconnect の前に端 末情報を保存しておいて、後で新しい pty にそのパラメタを 適用できる点にある。 & を 使っていて Expect が制御を受けとって disconnect されてしまうと、端末情報を読み込むこ とはできない。 exit [-opts] [status] Expect を exit させるか、そのための準備を行なう。 -onexit フラグは、続く引数を exit ハンドラとして用いる。 引数がなければ、exit ハンド ラは何もしない。 -noexit フラグを指定すると Expect は、exit の準備をして OS へ制御を返す直前に停止す る。 ユーザーの定義した exit ハンドラは、Expect 自身の内部ハンドラと同じように 実行 される。 それ以上 Expect のコマンドが実行されるべきではない。あなたが他の Tcl Extension を Expect につけている場合にこの機能は意味がある。 Expect の exit がもう一 度呼び出されると(こういう場合も起こり得る)、ハンドラは処理を 返さない。 exit する際に、全ての spawn されたプロセスへのコネクションはクローズされる。 クロー ズは EOF 検出によって行なわれる。 exit は、普通の exit(2) が行なう以上のことはしな い。 それで、spawn されたプロセスが EOF をチェックしない場合、そのプロセスは 走り続 ける。(spawn されたプロセスへ送られたシグナルを判断するといったこと には複数の条件が 関わってくる。これらは、システム依存であり、典型的な動作は 各システムの exit(3) のド キュメントに記述されている。) status (指定がないときは、0 )は、 Expect の、終了ステータスとしてシステムに返され る。 exit は、スクリプトの終りに達すると、書いていなくても実行される、 exp_continue [-continue_timer] exp_continue コマンドは expect 自身に待っていた値が来なかった時のように、expect の実 行を続ける。 デフォルトでは exp_continue は時間切れタイマーをリセットする。 -continue_timer フラグはタイマーを再実行しないようにする。 (より詳細な情報は expect を参照のこと。) exp_internal [-f file] value value がゼロでなければ、以降のコマンドの診断情報を Expect 内部の stderr に送るように なる。 value に0を指定するとこの出力は止まる。この診断情報には、受けとった すべての 文字と、現在の出力とパターンをマッチさせる全試行が 含まれる。 file オプションを指定すると、すべての通常および診断出力がそのファイルに 出力され る。( value の値とは無関係に)。すでにオープンされている診断出力ファイルは、 すべてク ローズされる。 -info フラグは、最後に指定された info フラグでない引数の内容を返す。 exp_open [args] [-i spawn_id] 元の spawn id に結びつけられたファイル ID を返す。 そのファイル ID は、Tcl の open コマンドでオープンした時と同様に扱える。 (spawn id は、もう使われるべきでない。 wait も実行すべきではない。) -leaveopen フラグは、spawn id をオープンしたままにしておく。 wait が、その spawn id に対して実行されねばならない。 exp_pid [-i spawn_id] 現在の spawn されたプロセスのプロセス ID を返す。 -i フラグを指示すると、与えられた spawn id に対するプロセスの 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 の現在のバージョンを返す。このバージョンはあなたのスクリプト 内で 設定しても良い。あなたが最近のバージョンに入った機能を使わないの であれば、もっ と前のバージョンを指定することができる。 バージョンはドットで区切られた 3 つの番号である。 最初の番号は、メジャー番号である。 違うメジャー番号の Expect 用に書いたスクリプトは、まず動かない。 exp_version は、メ ジャー番号がマッチしないとエラーを返す。 2 番めの番号はマイナー番号である。 使っている Expect よりマイナー番号がより大きい Expect 向けのスクリプトは、 新機能の使用未使用によるが、動かないかも知れない。 exp_version はメジャー番号がマッチしてもマイナー番号が使っている Expect のバージョン より大きいとエラーを返す。 3番めの番号は、バージョン比較には使われない。 しかし、文書の更新やプログラムの最適化 が行なわれて、 Expect のディストリビューションが更新されると、番号が増えていく。 新 しいマイナーバージョンが設定される度に、0 にリセットされる。 -exit フラグをつけると、バージョンが合わなかった時に Expect はエラーを表示し exit す る。 expect [[-opts] pat1 body1] ... [-opts] patn [bodyn] は、spawn されたプロセスの出力がパターンのどれかにマッチするか、 指定された時間が経 過するか、enf-of-file を見つけるか、のいずれかが 成立するまでウェイトする。 最後の body が空なら、それは省略できる。 一番最後に実行された expect_before コマンドのパターンが、どのパターンより先にチェッ クされる。 一番最後に実行された expect_after コマンドのパターンが、どのパターンより 後にチェックされる。 expect 全体への引数が 1 行に収まらなかった場合は、 引数を"ブレース"することで、各行 の終りにバックスラッシュをつけるのを 避けることができる。この場合、ブレースしたにも かかわらず通常の Tcl 展開が 発生する。 もし、パターンがキーワード eof であれば、end-of-file 発見時に処理が実行される。 も し、パターンがキーワード timeout であれば、タイムアウトが発生した時に処理が実行され る。 timeout キーワードが使われなかった場合、タイムアウト時にはなにもしない。 デフォ ルトタイムアウトは 10 秒である。設定することもできる。 例えば 30 秒と設定したけれ ば、"set timeout 30"を実行すること。 タイムアウトさせないためには、値 -1 を設定す る。 もし、パターンがキーワード default であれば、タイムアウトか end-of-file のいず れかで処理が実行される。 パターンにマッチすれば、処理は実行される。 expect は、行なった処理(関連するブレース 内の処理)の結果を返す。 (パターンにマッチしなかった時は、空文字列を返す。) 複数のパ ターンにマッチした場合、最初にマッチしたパターンに対応する処理が 実行される。 対話型プログラムからの新しい出力が Expect に届くたびに、リストされている順に パター ンとの比較が行なわれる。それゆえ、マッチすべきものがないことを 確認するために、プロ ンプトのように来ることがわかっているパターンを用意する ことができる。 プロンプトがな い場合には、(あなたが手で打つ時に判断しているように) timeout を用いなければならな い。 パターンは 3 通りに書ける。デフォルトは、Tcl の string match コマンドの書式であ る。(このパターンはグロブで参照される C-shell の正規表現に 似ている。) -gl フラグ は、他のマッチからパターンを保護するのに使う。 "-"で始まるパターンは、この方法で保護 すべきである。 ("-"で始まる文字列は将来の拡張で、オプションとして使われるかも知れな いから) 例えば、以下の断片はログインの成功を監視する。 (abort はスクリプトのどこか他の場所で 定義されていると仮定している。 注意すること。) expect { busy {puts busy\n ; exp_continue} failed abort "invalid password" abort timeout abort connected } 4番めのパターンにはスペースが含まれているのでクオートが必要である。 アクションとパ ターンを分離するセパレータでないことを指示する必要がある。 (3番めと4番めの)ように同 じアクションを持つリクエストも並べて書く必要が ある。これは、正規表現パターンを用い ることで回避できる(下記参照)。 グロブスタイルパターンについてもっと情報が欲しけれ ば、Tcl のマニュアルを 読むこと。 正規表現パターンは、Tcl の regexp ("regular expression"の短縮)コマンドで定義される文 法に従う。 regexpパターンは、 -re フラグで始める。 前の例を、regexp で書き直すと、こ うなる。: expect { busy {puts busy\n ; exp_continue} -re "failed|invalid password" abort timeout abort connected } どちらのパターンのタイプも、"固定されていない"。どういう意味かというと、 文字列全体 にマッチする必要はなくて、文字列のどこでもマッチすれば 良いということである。^ が先 頭にマッチする。 $ が末尾にマッチする。 文字列の末尾にマッチさせなければ、spawn され たプロセスからエコーされた 文字列の途中で切り上げてレスポンスを返せることに注意する こと。 正しく処理が実行されていても、出力は不自然に見える可能性がある。 それで、文字 列の終りの文字を正確に記述できるなら、$ を使うことを勧める。 多くのエディタでは、^ と $ は行頭、行末に正確にマッチする。 しかし、expect は行指向 ではないので、(行ではなく)データの始まりと終りに マッチする。 ("EXPECTヒント"内 の、バッファリングの消化不良に関する部分を参照のこと) -ex フラグは、"正確に(exact)"指示された文字列にマッチする。 * や ^ などの解釈は行な われない。(ただし、通常の Tcl 展開は行なわれる)。 Exact パターンは常に固定されてい る。 -nocase フラグは、小文字が含まれている場合に大文字に変換してからマッチさせる。 パ ターンには影響しない。 出力を読んでいて、2000 バイトを超えてしまったデータは"忘れられる"。 この動作は、 match_max 関数で変更できる。 (極端に大きな値はパターンマッチの性能を低下させることに 注意すること。) patlist に full_buffer を指定すると、 match_max バイト以上のデータを 受けてパターンマッチしなかったときに、処理が実行される。 full_buffer キーワードの有 無に関わらず、忘れられたデータは expect_out(buffer) に保存される。 patlist に、キーワード null を指定すると、ヌル文字が許可され ( remove_nulls コマンド を通して)、ヌル文字(ASCII 0)にマッチする。 glob や regexp では 0 バイトにマッチする ことができない。 パターン(あるいは、eol, full_buffer)にマッチすると、マッチした部分の文字列か、 その 前のマッチしなかった文字列が、変数 expect_out(buffer) に保存される。 9 個までのマッチした部分文字列は、変数 expect_out(1,string) から expect_out(9,string) に保存される。 -indices フラグをパターンの前で指定すると、マッ チした部分文字列の 開始位置と終了位置が( lrange の引数として使える形で)、変数 expect_out(X,start) と expect_out(X,end) に保存される。 X は数字で 0 〜 9 まで。 0 はパターン全体がマッチした部分を指示する。 例えば、プロセスが"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 は、 expect_out(spawn_id) に保存され る。 -timeout フラグは、この expect コマンドの中の timeout 時刻を timeout 変数でなく 指示 された値に設定する。 デフォルトでは、パターンはカレントプロセスからの出力にマッチさせるのだが、 -i フラグ を設定すると、指定された spawn_id リストに対応するプロセス群からの出力に マッチさせ ることができる。(次の -i での指定があるまで有効である。) spawn_id リストは、スペース で区切った spawn_id のリストか、そのような値を持つ 変数への参照でなくてはならない。 例えば、以下の例はカレントプロセスからの"connected"と $proc2 と言う名前の spawn_id からの"busy","failed","invalid password" を待ち受ける。 expect { -i $proc2 busy {puts busy\n ; exp_continue} -re "failed|invalid password" abort timeout abort connected } 大域変数 any_spawn_id の値は、 今の expect コマンド内で -i フラグを指示した spawn_id の全てにマッチさせるために使われる。 -i フラグをパターンなしで指定すると(すなわ ち、別の -i が直後に続くと)、 any_spawn_id で指定された、同じ expect コマンド内の他 のパターンに対して、有効になる。 -i フラグには、グローバル変数の名前を指定することもできる。その場合、 その変数 は、spawn id のリストである。変数は変わるたびに読み直される。 こうすることで、コマン ドが実行されている間に I/O ソースを変更すること ができる。この方法で指定される spawn id を"間接(indirect)" spawn id と呼ぶ。 break や continue などのアクションは、制御構造(すなわち、 for,proc )内で通常通りの振 舞いをする。 exp_continue コマンドは、 expect ループから抜けるような状況で実行を続けさせる。 ループを書いたり、expect コマンドを繰り返すことを避ける時に便利である。 以下の例はロ グインを自動化するコードの断片である。 exp_continue によって、(再びプロンプトを探す ための)2 つめの expect コマンドを書かなくて済んでいる。 expect { Password: { stty -echo send_user "password (for $user) on $host: " expect_user -re "(.*)\n" send_user "\n" send "$expect_out(1,string)\r" stty echo exp_continue } incorrect { send_user "invalid password or account\n" exit } timeout { send_user "connection to $host timed out\n" exit } eof { send_user \ "connection to host failed: $expect_out(buffer)" exit } -re $prompt } 例えば、以下の断片は既に自動化されているユーザーガイドへのやりとりを 補助する。 この 場合、端末は raw モードになる。 ユーザーが'+'を押すと変数がインクリメントされる。 "p"が押されると、プロセスへ復帰情報が送られる。 おそらくは同じように"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 と同様に、 expect_background コマンドは expect_before や expect_after パターンを使える。 expect_background アクションが、評価される時、同じ spawn id を持つ バックグラウンド プロセスはブロックされる。 アクションが完了すると、プロセスがアンブロックされる。 バックグラウンドプロセスがブロックされている間は、 (フォアグラウンドの) expect で、同じ spawn id に接続することができる。 逆に、 expect_background がブロックされて いない間は expect することができない。 特定の spawn id への expect_background は、同 一 spawn id への新しい expect_background を指定すると 削除される。 パターンをつけな い expect_background を指定することで、バックグラウンドでパターンマッチさせること を やめさせられる。 expect_before [expect_args] は expect と同じ引数をとるが、その場で復帰する。 もっとも最近、同じ spawn id に対し て expect_before で使われたパターン・アクションのペアが、続く expect コマンドに対し て使用される。 パターンがマッチすると、 expect コマンドにマッチした時と同じように動 作する。 処理は、その expect のコンテキストで行なわれる。 expect_before と expect の 両方のパターンにマッチした場合、 expect_before のパターンが使われる。 パターンが指示されなかった場合、spawn id は どのパターンでもチェックされない。 -i フラグをさらに指定しない限り、 expect_before パターンは、 expect_before が実行さ れた時に定義されたパターンにマッチする。 -info フラグは expect_before から、マッチパターンの現在の状態を復帰させる。 デフォル トでは、現在の spawn id に報告する。オプションの spawn id を 指定することもでき る。例えば、 expect_before -info -i $proc たった一つの spawn id 指定だけが許される。-indirect フラグで、直接 spawn id を抑止 し、間接的な指定から得られるidを指示する。 spawn id を指示する代わりに、"-all"フラグを使って、 全ての spawn id に "-info" の報 告をさせることができる。 -info フラグを使った時の出力結果は、expect_before への引数として 再利用できる。 expect_tty [expect_args] は、 expect と似た動きをするが、文字列を /dev/tty (すなわち、ユーザーからのキー入力) から読み込む。 デフォルトでは、cooked mode で読み込まれるので、 行はリターンで終らな ければならない。そうしないと expect が読めない。この動きは、 stty を使って変えられ る。 (下の stty コマンドを参照) expect_user [expect_args] は expect と似た動きをするが、文字列を stdin(すなわち、ユーザーからのキー入力) から 読み込む。 デフォルトでは、cooked mode で読み込まれるので、 行はリターンで終らなけれ ばならない。そうしないと expect が読めない。この動きは、 stty を使って変えられる。 (下の stty コマンドを参照) fork は、新しいプロセスを作る。この新しいプロセスは、現在の Expect プロセスの正確なコピー である。 成功すると fork は 新しい(子)プロセスに 0 を返し、親プロセスに 子プロセスの プロセスIDを 返す。 失敗する(スワップ、メモリなどのリソース不足か?)と、 fork は、親 プロセスに -1 を返す。新しい子プロセスは作成されない。 フォークされたプロセスは、 exit コマンドで ext できる。元のプロセスと同様である。 フォークされたプロセスはログファイルを作っても良い。多くのプロセスで デバッグもログ もできなければ、結果、混乱するだけである。 pty のインプリメンテーションの中には、複数の読み手と書き手が一瞬でもあれば、 混乱す るものがある。それで、プロセスを spawn する前には fork しておくのが一番安全である。 interact [string1 body1] ... [stringn [bodyn]] は、現プロセスの制御をユーザーに渡す。結果、 現プロセスに送られたキーストロークと現 プロセスの標準出力と標準エラー出力が 復帰する。 string と body の組が、引数として指示できる。(デフォルトでは、 文字列は現プロセスに は送られない) 最後の body がないと、 interpreter コマンドが実行される。 interact コマンド全体への引数が一行に収まらない場合、"brace"することで各行の終りに バックスラッシュを入れるのを避けることができる。この場合、Tcl の展開は ブレースして あっても起こる。 例えば、以下のコマンドは続く string body の組と対話する。 : ^Z が押されると Expect はサスペンドする。 ( -reset フラグは、端末モードを復旧させる。) ^A が押される と、ユーザーには"you typed a control-A"が返る。 $ が押されると、ユーザーには日付が返る。 ^C が押されると、 Expect は、exit する。 "foo"が入力されると、ユーザーに "bar" が返る。 ~~ が押されると、 Expect インタプリタ は、対話モードになる。 set CTRLZ \032 interact { -reset $CTRLZ {exec kill -STOP [pid]} \001 {send_user "you typed a control-A\n"; send "\001" } $ {send_user "The date is [exec date]."} \003 exit foo {send_user "bar"} ~~ } string と body の組で、string が引数として並べられた順に比較される。 部分的にマッチ した文字列は、残りが到着するまで送られて来ない。 何文字かさらに打ち込まれて、マッチ が可能になると、今のマッチを判断する ためにだけ使われて他のマッチを始めることはしな い。それゆえ、部分的に マッチしている文字列のマッチが完了するのは遅れることがある。 部分的にはマッチするが最終的にはマッチしない文字列の場合などである。 デフォルトでは、ワイルドカードを含まないマッチは、exactとなる。 ( expect コマンドが デフォルトでグロブスタイルのパターンを用いるのとは対照的に。) -ex フラグは、パターン をプロテクトするのに使える。 interact フラグがそうするように。 パターンが"-"で始まる 場合、この方法で保護できる。 ("-"で始まる文字列は全て将来のオプションとして予約され ている。) -re フラグは、正規表現スタイルのパターンとして文字列を解釈する。 この場合、マッチし た部分文字列は interact_out に保存される。 expect が、その出力を変数 expect_out に保 存するのと似たようなものである。 -indices フラグも同じようにサポートされる。 パターン eof は、end-of-file にマッチした場合にアクションを実行する。 複数に分かれた eof パターンには -output フラグが続いても良い。その場合、出力が書かれている間に eof が検出されると アクションを実行する。 eof のデフォルトアクションは"return"である。 それで、 interact は、EOF を見つけると復帰する。 timeout パターンは、(秒で表現された)タイムアウトにマッチし、アクションを実行する。 timeout パターンは、最後に指示されたプロセスに適用される。タイムアウトには デフォル トの値はない。(expect内で使われる)特殊な変数"timeout"は、 このタイムアウトと関係しな い。 例えば、以下の記述は一時間以上タイプしなかったユーザーを自動的にログアウト させ る。その前にシステムから頻繁にメッセージを受けとる: interact -input $user_spawn_id timeout 3600 return -output \ $spawn_id パターン null と nulls は、( remove_nulls コマンドを通して)、アスキーの 0 にマッチし た場合にアクションを実行する。 glob や regexp で 0 バイトにマッチさせることはできな い。 このパターンの前に -iwrite フラグをつけると、 変数 interact_out(spawn_id) にパター ン(あるいはeof)にマッチした spawn_id が設定される。 break や continue といったアクションは、制御構造 (すなわち、 for や proc )の中で、通 常通りに動く。 しかし、 return は、interact を呼出元に復帰させる。一方、 inter_return は、 interact をその呼びだし元内に復帰させる。例えば、"proc foo" は interact を呼ぶ。interact が、さらに、 inter_return を実行すると proc foo が復帰す る。(これは、 interact が、 interpreter を呼んで return とタイプすると、そ のinteractは継続するが、 inter_return すると、その呼出元に復帰してしまうということで ある。) interact の間 raw モードが使用されるので、全ての文字が現プロセスに渡される。 現プロ セスがジョブコントロールシグナルを捕まえなければ、 ストップシグナル(デフォルト^Z)で 停止する。再スタートするには、 制御シグナルを送る。("kill -CONT <pid>"とか打って)。 本当に SIGSTOP をプロセスに送りたいなら、csh を spawn してその上で プロセスを起動す ること。 そうでなくて、 Expect そのものに SIGSTOP を送りたいなら、インタプリタを呼び 出して (普通はエスケープ文字)、その後 ^Z を打つこと。 string bodyのペアは、インタプリタに入ってコマンドを対話的に実行するのを 避けることを 簡単に書くのに使われる。 前の端末モードが、その body を実行する間使用される。 実行速度を上げるには、デフォルトでアクションが raw モードで動くように する。 -reset フラグは、端末の持っているモードをリセットする。そうしなければ、 その前に行なった interact コマンドの端末モード(cooked モードとか)が保持される。 モードが切り替わった 時に、それまで打っていた文字が消えてしまうことが あるので注意すること。(システムに よっては、そういう不幸な仕様をした 端末ドライバが動いている。) -reset を使うのは、ア クションが cooked モードでしか動かない場合だけである。 -echo フラグは、一文字づつパターンにマッチする文字を返す。これは、 ユーザーが打つ文 字に部分的にマッチしなければならない場合に有効である。 パターンはエコーされたがマッチには失敗した場合、文字列は、spawn された プロセスに送 られる。それから、spawn されたプロセスが文字列を表示し、 ユーザーは文字列を二度見 る。 -echo は、ユーザーがパターンを完成させてくれそうもない場合にだけ有効であろう。 例えば、以下は rftp(リカーシブ ftp スクリプト)からの抜粋だが、ユーザーが ~g, ~p, ~l を打つとカレントディレクトリから再帰的(リカーシブ)に get, put, list する。通常の ftp ではこれらの操作ができない。間違って ~ を 打つか、~ の後を間違えた場合、その文字列を 無視するようになっている。 interact { -echo ~g {getcurdirectory 1} -echo ~l {getcurdirectory 0} -echo ~p {putcurdirectory} } -nobuffer フラグは、文字が読まれる度に、その文字をマッチへ送る。 このフラグは、パターンをエコーバックする時に有効である。 例えば、以下は誰かが(ヘイズ モデムを)ダイアルするのを監視するのに 使われる。"atd"が見える度にスクリプトが残りの ラインをログする。 proc lognumber {} { interact -nobuffer -re "(.*)\r" return puts $log "[exec date]: dialed $interact_out(1,string)" } interact -nobuffer "atd" lognumber interact の間、前に使った log_user は無視される。特に、 interact は、その出力を記録 される(標準出力に送られる)。 というのは、ユーザーはエコーバックのない状態でキーを打 ちたくはない だろうと考えるからである。 -o フラグは、現プロセスの出力に key body ペアの key を結びつける。 こんな場合に便利 である。例えば、telnet セッション中に望まない文字を 送ってくるホストを扱う場合であ る。 デフォルトでは、 interact は、ユーザーが Expect プロセス自身の標準入力に書き込み、標 準出力を見ていると思っている。 -u フラグ("user"のu)は interact に、引数で付けられた 名前(spawned id である)のプロセスをユーザーとして 扱う。 これにより、変なループなしに2つの無関係なプロセスを結合させることが できる。デバッグ する時の助けとして、Expect は常に診断結果を stderr へ送る。(ある種のログとデバッグ情 報は stdout に送られる)。 同じ理由で、 interpreter コマンドは、stdin からデータを読 む。 例えば、以下の断片はログインプロセスを作る。そして、(表示されない) ユーザーにダイア ルし、両方の接続を行なう。 もちろん、loginをどんなプロセスに変えても良い。例え ば、シェルなら、ア カウントとパスワードを与えなくてもユーザーが起動できる。 spawn login set login $spawn_id spawn tip modem # dial back out to user # connect user to login interact -u $login 複数のプロセスへの出力を行なうため、 -output フラグを前につけた各 spawn id のセット がリストされる。 出力 spawn id の組への入力は、 -input フラグによって決定される。 ( -input と -output フラグは両方とも expect コマンドの -i フラグと同じ書式である。( interact 内の any_spawn_id は意味がない点を除く。) 以下のフラグと文字列(あるいはパ ターン)は全て、別の -input フラグが現れるまで この入力を適用する。 -input が現れな かった場合、 -output は "-input $user_spawn_id -output" を行なう。 ( -input を持たな いパターンも同様である。) -input が一つだけ指示されると、$user_spawn_id はその値で置 き換わる。 二つめの -input が指示されると、$spawn_id が置き換わる。 以降の -input フ ラグも指定できる。 2つの入力プロセスはデフォルトで $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 は、呼出元への復帰を行なうのに対し、 inter_return は interpreter を、呼出元を 復帰させる。たとえば、 "proc foo" は、 interpreter を呼び、 inter_return を実行し proc foo が復帰する。 他のコマンドは interpreter に新しいコマンドのためのプロンプト を表示し続ける。 デフォルトでは、プロンプトは 2 つの整数を含んでいる。 最初の数は評価スタックの深 さ(つまり、何回 Tcl_Eval が呼ばれたか) 2番めの数は、Tcl ヒストリ識別番号である。プロ ンプトは "prompt1"と呼ばれるプロシジャを定義することで設定できる。 このプロシジャの 帰り値が次のプロンプトとなる。 記述に開きクオート、括弧、ブレース、ブラケットがある と、次の行には 第 2 プロンプトが現れる(デフォルトは "+> ")。第 2 プロンプトは "prompt2"と呼ばれるプロシジャを定義することで設定できる。 interpreter の間は、呼出元が raw モードであったとしても、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 フラグは、最後にログした内容を返す(最後が-infoフラグ付きだったら、 その前の内 容)。 log_user -info|0|1 デフォルトでは、send/expect ダイアログは標準出力にロギングされる。 (開いていればログ ファイルにもロギングされる。) "log_user 0"とすると、標準出力へのロギングが抑止され る。 "log_user 1"とすると、復旧する。ログファイルへの記録については 変更はない。 -info フラグは、最後にログした内容を返す(最後が -info フラグ付きだったら、 その前の 内容)。 match_max [-d] [-i spawn_id] [size] は、バッファサイズを(バイト単位で)定義する。このバッファは、 expect の内部で使われ る。 引数 size がないと、現在のサイズを復帰する。 -d フラグを指示すると、デフォルトサイズが設定される。(初期状態の デフォルト値は 2000。) -i フラグを指示すると、名前つき spawn id に対してサイズが設定される。 指定し なければ、カレントプロセスに対して設定される。 overlay [-# spawn_id] [-# spawn_id] [...] program [args] は、 program args を現在の Expect プログラム上で実行する。現在の Expect プログラムは 終了する。 ただのハイフンが引数に指定されると、コマンド名の前にハイフンをつけて ログ インシェルとして扱う。 全てのクローズ中の spawn_id は、引数に使われた文字列を待つ。 Spawn_id は、新しいプログラムに継承させるためのファイル ID に マップされる。例え ば、以下の行はチェスを行ない、chess master という現プロセスに制御させる。 overlay -0 $spawn_id -1 $spawn_id -2 $spawn_id chess これは、 "interact -u" とするよりも効果的である。しかし、 Expect プロセスが制御して いないのでプログラム能力が犠牲となる。 制御されない端末ができてしまうことに注意すること。それで、 disconnect するか標準入力 をリマップするとジョブ制御プログラム (シェル、ログインなど)が正しく機能しない。 parity [-d] [-i spawn_id] [value] は、spawn idの出力からパリティを保持するか取り除くかを設定する。 value が 0 であれ ば、パリティは取り除かれる。 それ以外の場合、取り除かれない。 value が指定されない場 合、現在の値が復帰する。 -d フラグは、パリティのデフォルト値を設定する。(イニシャル時のデフォルト値は 1 であ る。すなわち、パリティが取り除かれる。) -i フラグを指示すると、パリティの値が引数の 名前つきの spawn id に対して 設定される。引数がなければ現在のプロセスに対して設定さ れる。 remove_nulls [-d] [-i spawn_id] [value] は、前にパターンマッチしたあるいは expect_out か interact_out に保存されている spawn されたプロセスの出力からヌルを保持するか取り除くかを 設定する。 value が 1 なら、ヌ ルは取り除かれる。もし、 value が 0 なら、ヌルは取り除かれる。 value がなければ、現 在の値が復帰する。 -d フラグは、デフォルト値を設定する。(イニシャルのデフォルト値は、 1 である。それゆ え、ヌルは取り除かれる。) -i フラグは、名前つきの spawn id に対して値を設定する。な ければ、 現プロセスに対して設定する。 ヌルを取り除くかどうかによらず、 Expect は、ログと標準出力にはヌルが記録される。 send [-flags] string string を現プロセスに送る。 例えば、以下のコマンド: send "hello world\r" は、文字 h e l l o <blank> w o r l d <return> を現在のプロセスに 送る。 (Tcl は、printf に似たコマンド ( format と呼ばれる )を持っていて、複雑な文字列を組み立て ることができる。) 文字は直ちに送られる。ただし、入力にラインバッファのあるプログラムでは、 リターン コードが送られるまで文字が読まれない。リターンコードは、 "\r"と表記する。 -- フラグは、続く引数をフラグと解釈せず文字列として解釈される。 全体としてフラグに見 えなくても"--"が前についた文字列はフラグとして 扱われてしまう。このフラグは処理され ていない文字列がフラグとして 扱われるのを防ぐ。 ("-"で始まる文字は全て将来のオプショ ンとして予約されている。) -i フラグは、名前つきの spawn_id に文字列を送ることを宣言する。 その spawn_id が user_spawn_id であれば、端末はraw モードに入り、文字列中の改行が復帰改行シーケンスに 変換される。それで、外からは 端末が cooked モードとなっているように 見える。 -raw フ ラグは、この変換を抑止する。 -null フラグは、ヌル文字を送る(0 バイト)。デフォルトでは、ヌル文字を 1つ送る。 -null に続く整数はヌル文字をいくつ送るかを指示する。 -break フラグは、ブレーク状態を作る。spawn id が"spawn -open"で指示した tty デバイス を参照する場合のみ意味がある。tip などのプロセスを spawn する場合、tip の都合で ブ レーク状態を作るべきである。 -s フラグは、出力を強制的に"遅く"する。結果、コンピュータが打ち込んでいる バッファに 人間が打ち込んでしまう状況を避けることができる。この出力は 変数"send_slow"の値で制御 される。この変数は二つの要素を持つリストである。 最初の要素は、アトミックに送るバイ ト数である。2 番めの要素はアトミックに送る 間隔(秒)である。例えば、 "set send_slow {10 .001}" は "send -s" に 10 文字送る毎に1ミリ秒待つように指示する。 -h フラグは、人間の実際の入力に似せて send を行なう。(アルゴリズムは、 Weibull distribution に基づいていて、この特定のアプリケーション Expect? に 合わせるための修 正が行なわれている。) この出力は変数"send_human"の値で制御されていて、この変数は 5 つの要素から なるリストで最初の 2 つの要素は文字間の平均インターバル時間(秒)である。 1 つめがデフォルト値で、2 つめが(通常発生する微妙な待ち時間を表現する) 単語の終りの 値である。3 つめの要素は変動率である。 可能な値は 0 から 無限大である。最後の 2 つの パラメタは、それぞれ、 インターバル時間の最小値と最大値である。この 2 つの値は最後に 使われて、 最終時刻をクリップする。この 2 値が違うと究極の平均は与えられた平均とは、 全く違ったものになる。 例として、続くコマンドが一定の速度で速く打つタイピストを エミュレートする: 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 にエラーや修正を埋め込んであっても、 エラーはシミュレートされない点に注意するこ と。 ブレークを送るためや、ゆっくりした出力を行なったり、人間が出力したように 見せかける ためにヌル文字を送るフラグは相互排他される。 最後に指定されたものだけが使われる。そ れ以上は、 string の引数が、ヌル文字あるいはブレークを送るフラグとして指定できる。 最初の send より前に expect を置いた方が良い。 expect は、プロセスが始まるのを待てる が、 send は待てない。 特に、最初の send は、プロセスが走り始める前に完了する。あな たのデータが無視される 危険がある。 最初にプロンプトを表示しないような対話的なプログ ラムでは、 次のように send の前にディレイをつけることができる: # どのように破るかのヒントをハッカーに与えてしまわないように、 # このシステムでは外部のパスワードに対するプロンプトを提供しない。 # exec が完了するのを 5 秒待て。 spawn telnet very.secure.gov sleep 5 send password\r exp_send は send のエイリアスである。あなたが Expectk か、Tk 環境で動く Expect の他 の変種を 使っている場合、 send は、全く異なった目的のために使われている。 exp_send が、両環境の間での互換性のために提供されている。 似たようなエイリアスが他の Expect の他の send コマンドのために提供されている。 send_error [-flags] string send と似たようなもので、現プロセスでなく stderr に出力される。 send_log [--] string send と似たようなもので、ログファイルだけに string を送る。( log_file を参照。) 引数 はログファイルが open されていなければ無視される。 send_tty [-flags] string send と似たようなもので、現プロセスでなく /dev/tty へ出力を送る。 send_user [-flags] string send と似たようなもので、現プロセスでなく標準出力へ出力を送る。 sleep seconds は、与えられた数字の秒数だけスクリプトがスリープする。 seconds は、10進数だけが許さ れる。 (Expectk を使っている場合、Tkのイベントと)割り込みは、Expectが スリープしてい る間も処理される。 spawn [args] program [args] program args を走らせる新しいプロセスを生成する。その標準入力と標準出力は Expect に 結びつけられる。それで、他の Expect コマンドで読んだり書いたりできる。 接続は close によって、あるいは、プロセスそのものがファイル ID の いずれかをクローズした場合、破 壊される。 プロセスは spawn によって始められる。変数 spawn_id には、そのプロセスへの参照を行な う識別子が設定される。 spawn_id によって記述されるプロセスは current process が考慮 される。 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, バッチスクリプトの中)場合、 tty_spawn_id は定義されない。以下の ように確認することができる。: if {[info vars tty_spawn_id]} { # /dev/tty exists } else { # /dev/tty doesn't exist # probably in cron, batch, or at script } spawn UNIX プロセス ID を復帰する。spawn されたプロセスがない場合、0 が 復帰する。変 数 spawn_out(slave,name) は pty スレーブデバイスの名前に設定される。 デフォルトでは、 spawn はコマンド名と引数をエコーする。 -noecho フラグで spawn がこ うするのを止められる。 -console フラグは、コンソールへの出力を起こし、spawn されたプロセスへの リダイレクト される。この機能は未サポートのシステムがある。 内部的に、 spawn は pty を使い、ユーザーの tty と同じように初期化される。これは、か なり 初期化してしまうので全ての設定が (stty(1)によると) "正常(sane)" になる。 変数 stty_init が定義されていると、stty の引数の形式を解釈できるので、より詳細な設定を 行 なえる。例えば、 "set stty_init raw" は、以降 spawn されたプロセスの端末を raw モー ドで開始する。 -nottycopy は、ユーザーの tty に基づいた初期化を飛ばす。 -nottyinit は、"正常な"初期化を飛ばす。 普通、 spawn は、実行するのにわずかの時間しかかからない。spawn に時間をかけたいので あれば、おそらく割り込まれた pty に遭遇するだろう。たくさんのテストが 間違ったプロセ スに掛かり合うことを避けることができる。 (割り込まれた pty につき、10 秒かかる。) -d オプションをつけて Expect を走らせると、 Expect がおかしな状態のたくさんの pty に遭 遇しているかどうかが表示される。 これらの pty がつながっているためにプロセスを殺せな い場合、リブートするしか 頼れる復旧手段はない。 exec(2)が失敗して program が spawn に成功しなかった場合 (例えば、 program がなかった 場合など)、エラーメッセージが次の interact か expect コマンドで復帰する。つまり。 program が、出力としてエラーメッセージを出しているように見せる。 この動作は、 spawn の実装の自然な帰結である。内部で、spawn がフォークされ、その後、 spawn されたプロセ スがオリジナルの Expect プロセスとその spawn_id で会話を行なう。 -open フラグは、次の引数を Tcl ファイル識別子として解釈する(つまり、 open を行なって 復帰する。 ) spawn id は、spawn された id として使われる。(ファイル識別子は、 もう使 うべきではない。) これにより、 pty を除く、raw デバイス、ファイル、パイプラインを使 うことができる。 0 が返ってくるのは、関連するプロセスがなかった時である。 spawn され たプロセスへの接続がクローズされると、Tcl ファイル識別子も クローズされる。 -leaveopen フラグは、 -open と似た動きをするが、 spawn id をクローズした後もファイル 識別子を開いたままにする点が違う。 -pty フラグは、 pty をオープンするがプロセスをspawnしない。0 が復帰するのは、 関連す るプロセスがない場合である。spawn_id は、通常通り設定される。 変数 spawn_out(slave,fd) には、pty スレーブとつながっているファイル識別子が設定され る。 "close -slave" で close できる。 -ignore フラグは、spawn されたプロセス中で無視されるシグナルの名前を指示する。 なけ れば、シグナルはデフォルトの振舞いをする。シグナルの名前は trap コマンドで使う名前と 同じである。各シグナルを分離するのにフラグが 必要な点を除いては。 strace level は、以降の命令を実行する前に表示を行なう。 (Tcl の trace は、変数のトレースを行な う。) level は、トレースへの呼び出しスタックの深さを示す。 例えば、 以下のコマンドは Expect 最初の 4 レベルの呼び出しをトレースする。 それ以上の深さはトレースしない。 expect -c "strace 4" script.exp -info フラグを指定すると、strace は最後の info でない指定の内容を復帰する。 stty args は端末モードを変更する。外部の stty コマンドと似たようなものである。 デフォルトでは、制御している端末がアクセスされる。他の端末は、 "< /dev/tty..." を追 加することでアクセスできる。(引数を一つの引数に まとめるべきではない。) ステータス要求はコマンドの結果としてステータスを復帰する。 ステータスが要求されずに 制御している端末にアクセスする場合、直前の raw と echo の状態を返す。 例えば、引数 raw か -cooked は、端末を raw モードに設定する。 引数 -raw か cooked は、端末を cooked モードに設定する。 引数 echo か -echo は、端末をそれぞれ echo ある いは noecho モードに設定する。 以下の例は、一時的なエコー禁止をどうやっておこなうかを示す。 これは、他の自動スクリ プトで、その中にパスワードが埋め込まれるのを 防ぐことに使われる。(もっと議論したけれ ば、下の EXPECT ヒントに ある。) stty -echo send_user "Password: " expect_user -re "(.*)\n" set password $expect_out(1,string) stty echo system args は、 args を、sh(1)に入力する。端末からコマンドを叩くのとちょうど同じである。 Expect は、シェルが終るのを待つ。sh からの復帰値は、 exec がその復帰値を扱うのと同じに扱わ れる。 exec が、スクリプトに標準入出力をリダイレクトするのと対照的に、 対照的に 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, 最初の日曜日が第1週の最初の日) %V 週 (01-53, ISO 8601 スタイル) %w 日 (0-6) %W 週 (00-53, 最初の月曜日が第1週の最初の日) %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 この他の % 指定は定義されていない。他の文字は変更されない。 C ロカールだけがサポート される。 -seconds フラグは、 タイムスタンプを秒で表す。 -gmt GMT タイムゾーンで出力する。デフォルトはローカルタイムゾーンである。 trap [[command] signals] を実行すると、以降指定された signal を受けとると指定された command を実行する。 この コマンドは、グローバルスコープで実行される。 もし、 command が指定されなければ、シグ ナルアクションが復帰する。 command が、文字列 SIG_IGN であれば、シグナルが無視され る。 command が、文字列 SIG_DFL であれば、シグナルはデフォルトの動きをする。 signals は、シグナルが1つでも複数のシグナルのリストでも良い。シグナルは、 数字とsignal(3)に 記述されている文字列のどちらで指定しても良い。 プレフィクスの"SIG"は、省略しても良 い。 引数がなければ(または、引数 -number であれば)、 trap は、trapコマンドで横取りされて いるシグナル番号を復帰する。 -code フラグはコマンドコードを返す。Tcl がコマンドを動かし始めた時に 帰そうとした コードである。 -interp フラグは、trap が宣言された時でなくコマンドが開始された時にインタプリタに コ マンドを評価させる。 -name フラグは、 trap コマンドに trap のかかっているシグナル名を帰す。 -max フラグは、 trap コマンドに設定できる最も大きなシグナル番号を帰す。 例えば、"trap {send_user "Ouch!"} SIGINT" は、 ユーザーが ^C を押す度に "Ouch!" を表 示する。 デフォルトでは、SIGINT(通常 ^C を押すと発生する)や SIGTERM は、Expect を exit させて しまう。これは、Expect が起動時に 実行する以下の trap によって起こっている。 trap exit {SIGINT SIGTERM} -Dフラグを使ってデバッガを起動するなら、SIGINT が再定義されてから対話型 デバッガが起 動される。これは以下の trap によって起こる。 trap {exp_debug 1} SIGINT デバッガのトラップは、環境変数 EXPECT_DEBUG_INIT を設定して、新しく trap を起動する ことで変更できる。 もちろん、スクリプトにtrapコマンドを足すだけで例のトラップは両方とも 上書きでき る。特に、自作の "trap exit SIGINT" があるなら、これは デバッガのトラップを上書きし てしまう。ユーザーにデバッガを全く 触らせないようにするのに、便利である。 SIGINT のトラップを独自に定義したいけれど、デバッガにも同時に割り込んで もらいたいの であれば、こう書く。: if ![exp_debug] {trap mystuff SIGINT} 代わりに、別のシグナルを使ってデバッガに割り込みをかけることができる。 trap は、SIGALRM のアクションを上書きしない。 Expect が内部で使用しない。 disconnect コマンドは、SIGALRMを SIG_IGN (ignore)に設定する。 後から発行される spawn コマンドを 実行している間、SIGALRM は ディスエーブル中であれば再度イネーブルにできる。 もっと情報が欲しい場合、signal(3) を参照すること。 wait [args] は、spawn されたプロセス(あるいは、名前つきのプロセスがなければ現在のプロセス) が終 了するのを待つ。 wait は、通常 4 つの整数のリストを帰す。 最初の整数は、終了を待ち構えているプロセス の pid である。 2 つめの整数は、関連する spawn id である。 3 つめの整数は、オペレー ティングシステムエラーがあれば -1、 そうでなければ、0 である。 3 つめの整数が 0 であ れば、4 つめの整数はspawnされたプロセスからのリターン コードである。3 つめの整数が -1 であれば、4 つめの整数はオペレーティングシステム によって設定された errno の値で ある。グローバル変数 errorCode も設定される。 追加の要素が wait の復帰値に加わっても構わない。オプションの5つめの要素は、情報クラ スの 識別子である。今のところ、この要素の唯一可能な値は CHILDKILLED で、 その場 合、次の二つの値が C スタイルのシグナル名と短い文書による記述である。 -i フラグによって、wait を行なう名前付き spawn_id(プロセス ID ではなく)を 指定す る。SIGCHLD ハンドラの内部では、spawn ID -1 を指定することで、 spawn されたプロセス のいずれかを wait できる。 -nowait フラグを指定すると、wait が成功の復帰値で即時復帰する。 (あとで)そのプロセス が exit すると、自動的に後始末が行なわれ、明示的に wait する必要がない。 wait コマンドは、引数に "-i -1" を指定することによって、 fork したプロセスを待つため にも使われる。 spawn したプロセスに用いられる場合と異なり、 このコマンドはいつでも実 行できる。 どのプロセスを待つかを制御することは出来ないが、 返り値はプロセス ID とし てチェックできる。
ライブラリ
Expect は、スクリプトのための二つのビルトインライブラリを自動的に理解する。 それらは変数 exp_library と変数 exp_exec_library に設定されたディレクトリ名と して定義される。これらの ディレクトリには、他のスクリプトによって使える ユーティリティファイルが入っている。 exp_library には、アーキテクチャに依存しないファイルが格納される。 exp_exec_library に は、アーキテクチャに依存するファイルが格納される。 あなたのシステムによっては、両方のディ レクトリが空という場合もあり得る。 ファイル $exp_exec_library/cat-buffers の存在は、あなた のシステムの /bin/cat がデフォルトでバッファリングされているかどうかに左右される。
整形印刷
Expect スクリプトをきれいに印刷するための vgrind の定義がある。 Expect ディストリビュー ションと一緒に配布されている vgrind 定義が正しく インストールされていると仮定して、こうす れば使える。 vgrind -lexpect file
例
マニュアルページによる記述では、あらゆるものをどう組み合わせるのかと いうことが明白ではな い。私としては、 Expect ディストリビューションの example ディレクトリにある例を読んで試し てみて欲しいと思う。 いくつかは本物のプログラムである。それ以外は特定のテクニックの単純な 解説、 あと、もちろん、単なるクイックハックが少しある。 INSTALL ファイルにはこれらのプログ ラムの簡単な梗概が書かれている。 Expect の論文も役に立つ(関連項目参照)。いくつかは、初期バージョンの Expect の 文法を使って いるが、それとともにある根本的な考えは、なお有効であり、 このマニュアルページより詳細に書 かれている。
警告
拡張は Expect のコマンド名と衝突するかもしれない。例えば、 send は、Tk では全く別の目的で 定義されている。 そういう理由で、ほとんどの Expect コマンドは、"exp_XXXX" という 別の記 法(エイリアス)もサポートする。 "exp", "inter", "spawn", "timeout" で始まるコマンドと変数 は、 エイリアスを持たない。 この環境間の互換性が必要であれば、拡張されたコマンド名を用いる こと。 Expect は、かなり自由なスコープを持っている。特に、 Expect プログラムで指定したコマンドに より読み込ませる変数は、そのローカルスコープ 内でまず探索され、見つからなければ、グローバ ルスコープで探索される。 例えば、こうすることで expect を使う全てのプロシジャに "global timeout" を書く必要が なくなる。 逆に、プロシジャ内に書かれた変数は全てローカルスコープ内 に設定される。 ("global"コマンドを指定しない限りは)。この動作が引き起こすもっとも共通した 問題は、spawn がプロシジャ内で実行された時である。プロシジャの外では、 spawn_id はスコープ のため、もはや存在しないので spawn されたプロセスは単純には アクセス不能となる。そのような プロセスには、"global spawn_id"を 付け加えねばならない。 multi-spawn 機能が使えない(つまり、あなたのシステムが select (BSD *.*), poll (SVR>2),また は、それと等価なもの のいずれも サポートしていない)場合、 Expect は、同時に 1 プロセスしか 制御できない。 この場合、 spawn_id を無理に設定したり、spawn されたプロセスが走っている間 に exec を使って プロセスを実行したりしてはならない。さらに、複数のプロセス(片方が ユー ザーでも)から同時に expect することもできない。 端末制御パラメタは、スクリプトに大きな影響を与える。例えば、 スクリプトがエコーを探すよう に書かれていれば、エコーをオフにすると 動作がおかしくなる。この理由で、Expect はデフォルト で 正気の 端末パラメタを設定する。不幸なことに、この設定が他のプログラムではまずい 場合が ある。例えば、emacs シェルは"通常の"マッピングを変更しようとする。 : newlinesは、carriage- return newlines に変換されず newlines にマップされる。 そして、エコーは行なわれない。こう マップされることで、emacs は入力行を 編集できる。残念ながら、Expect はこのマッピングを検出 できない。 Expect が端末パラメタのデフォルト設定を上書きしないように指定することが できるが、そういっ た環境で動かすスクリプトを書くときは細心の注意が 必要である。emacs の場合、エコーや改行 コードのマッピングを回避しなければ ならない。 ( expect とその変種、および、 interact といった)1 つのリストにブレースされた引数を受けとる コマンドは、 リストが引数をどれだけ持っているのかを判断するのに、発見的手法を用いる。 その 発見的手法はが失敗する唯一の場合は、引数の一つに複数の\nが埋め込まれ、 その間にホワイトス ペースがない場合である。これは十分検出不能な状態だが、 引数"-nobrace" で、強制的に一つの引 数として扱うことができる。 自動的に生成された Expect コード中で使われるかもしれない。 同様 に、-brace は複数のパターン/アクションをひとつの引数として扱うことを 強制する。
バグ
プログラムに "sex" ("Smart EXec" か "Send-EXpect" の略) という名前を つけるのは実に魅力的 だったのだが、センスの良い方(あるいは、 単にピューリタニズム)が優先された。 シェルが spawn されるとttyにアクセスできないと文句をいって、しかし、動作はする というシス テムがある。これは、このシステムがtty制御を得るための機構を 持っているが Expect はそれを知 らないという意味である。どういう仕組みか調べて、その情報を私に 知らせてほしい。 Ultrix 4.1 (少なくとも最新バージョンのあたり) では、 1000000 を超えるタイムアウトを 0 とみ なしてしまう。 Digital UNIX 4.0A (おそらく他のバージョンも)は SIGCHLD ハンドラを 定義すると、pty の割り付 けを拒否する。詳細は grantpt ページを参照のこと。 IRIX 6.0 は、pty へのアクセス制御を正確に扱えない。それで、 Expect は、pty がアロケートで きない場合は、他の人が前に使った pty の アロケートを試みる。 IRIX 6.1 にアップグレードする こと。 telnet (SunOS 4.1.2 でのみ確認)は、TERM が設定されてないと ハングする。この問題は cron や at や CGI スクリプトで使う時に問題だ (設定しないので)。それで、 明示的に指定しなくてはなら ない - 本当のタイプは通常関係ない。 何かに設定してないと駄目なのだ! 以下の記述はおそらくほ とんどの場合を 満足させるだろう。 set env(TERM) vt100 tipt (BSDI BSD/OS 3.1 i386 でのみ確認)は、SHELL と HOME が設定されてないと ハングする。こ の問題は cron や at や CGI スクリプトで使う時に問題だ (設定しないので)。それで、 明示的に 指定しなくてはならない - 本当のタイプは通常関係ない。 何かに設定してないと駄目なのだ! 以下 の記述はおそらくほとんどの場合を 満足させるだろう。 set env(SHELL) /bin/sh set env(HOME) /usr/local/bin pty のインプリメントの中には、プロセスがファイル記述子をクローズした後、 読んでない出力を 10 から 15 秒後(この値はインプリメントに依存)に投げてくる ものがある。それゆえ、 spawn date sleep 20 expect のような Expect プログラムは失敗する。失敗しないように非対話的なプログラムでは spawn せず に exec すること。こういう状況は考えられるが、実際には私はまだその状態に 陥ったことがな い。つまり、この原因で対話プログラムの最後の出力を 取りこぼすという状態になったことがな い。 一方、Cray UNICOS の pty は読み込んでいない出力をファイルディスクリプタを プロセスが閉じる とすぐに投げてくる。私は Cray にこの動きについて報告し、 回避するための修正を行なった。 プロンプトと応答の間にディレイが必要な場合がある。tty インターフェースが UART の設定を変え たり、スタート/ストップビットを探してボーレートを合わせて いる時などである。通常、ここで必 要とされているものは 1 秒か 2 秒の待ち合わせである。 もっとしっかりしたやり方はハードウェ アが入力を受ける準備ができるまで繰り返す ことである。以下の例は、両方の戦略を採用してい る。: send "speed 9600\r"; sleep 1 expect { timeout {send "\r"; exp_continue} $prompt } -code をトラップするのは Tcl のイベントループに依存しているコマンド (sleep など)では動かな い。 問題は、イベントループの中では Tcl は非同期イベントハンドラからの 返り値を捨てている からである。 回避方法としては、トラップコードでフラグをセットし、 コマンド(sleep など)の直 後でフラグをチェックすることである。
EXPECT ヒント
Expect について、直観的でない点が少しある。 このセクションではそういったことの指摘とそれに 対する示唆を試みる。 共通の expect の問題は、シェルプロンプトを認識する方法である。 その設定も、それを扱う人 も、使うシェルもまちまちなので、実際に出てくる プロンプトを知らずに、汎用的に rlogin を自 動化することは困難である。 妥当な線は、ユーザーにプロンプトにマッチする正規表現(特にプロン プトの 終りの部分)を環境変数 EXPECT_PROMPT に保存させることである。 以下のようなコードでで きる。 EXPECT_PROMPT がなくても、コードは正しく動く可能性がある。 set prompt "(%|#|\\$) $" ;# default prompt catch {set prompt $env(EXPECT_PROMPT)} expect -re $prompt 私としては、見えると思っているものの終りの部分を含んだ expect パターンを書くように勧め る。そうすれば、全体を見る前に応答を返してしまう ことを避けることができる。さらに、全体が 見える前に答えることもできるが その文字は質問に混ざって echo される。言い替えれば、会話は 正常だが見た目は 混ざって見える。 ほとんどのプロンプトの終りの文字はスペースである。例えば、 ftpからのプロンプトは、'f', 't', 'p', '>' そして <blank> である。 このプロンプトにマッチさせるには、この文字の一つ一つ にマッチしなければ ならない。blank を含めないのは、よくある誤りである。明示的に blank を 入れるように。 X* の形のパターンを使うのであれば、* はXから最後に受けとる何かまでの 全てにマッチする。こ れは一見直観的だが、"最後に受けとる何か"が コンピュータの速度とカーネルとデバイスドライバ によるI/O処理によって 変わってしまうので混乱するだろう。 特に、人間はプログラムの出力が巨大なひとまとまりとしてやってくると思いがち だが、実際に は、ほとんどのプログラムは一行を一度に送る。 こう仮定すると、直前の段落のパターンにあった * は、行の終りにしか マッチしないかも知れない。たとえ、もっと入力があると思われる場合でも 出力を全て受けとった時点でしかマッチを行なわないのである。 expect は、指定したパターンが教えてくれない限り、出力がさらにやってくるのか どうかわからな い。 行指向のバッファリングを行なっている場合ですら、賢いやり方とはいえない。 プログラムはバッ ファリングのタイプをめったに保証しないだけでなく、その際に 消化不良を起こして出力行を中断 し、行末をバッファ中のランダムな位置に 置いてしまう。 それで、パターンを書く時には、プロン プトの最後の何文字かを入れておいた方が 賢いやり方といえるのである。 プログラムの最後の出力にあるパターンを待ち、実際には何がしか他のものが 発行されている場合 には timeout キーワードで判定することができない。理由は、 expect が、タイムアウトしない - そのかわりに eof を見つけられる - からである。 代わりになるものを使うこと。もっと良いの は、両方使うことだろう。 行が回り込んだ場合でも、行そのものを編集するべきではない。 tty ドライバによって出力される時に newline は、普通 carriage return, linefeed の組に変換さ れる。 それで、2 ラインにマッチするには、例えば、printf("foo\nbar") に マッチさせるに は、"foo\r\nbar" というパターンを使うことになる。 似たような変換は、ユーザーから expect_user を通して入力を読み込む時にも起こる。この場 合、ユーザーがリターンを 押すと、それは newline に変換される。その後、 Expect が端末モード を raw モード(telnet のような)を設定すると、問題が発生する 可能性がある。プログラムが本当 のリターンを待ってしまうからである。(プログラムの 中には、newline をリターンに変えても大丈 夫なものもあるが、ほとんどはだめである。) 残念ながら、プログラムが端末を raw モードにする ことを検出する方法がない。 手で newline をリターンに変えるのではなく、"stty raw"を使うのが解決策である。 stty raw は、変換を停止する。しかし、こうすると cooked モードの行編集機能が 使えなくなるということ に注意すること。 interact は、端末を raw モードに設定するので、この問題は発生しない。 Expect スクリプトの中でパスワード(や他の機密情報)を保存すると便利なことは よくある。だれか のアクセスを受けるとその影響を受けてしまうコンピュータで そういうことをするのは勧められな い。それで、パスワードのプロンプトを スクリプトから出すのが、文字通りパスワードを埋め込む よりは、良い考えと いえる。とはいうものの、そういった埋め込みをするしかない場合もある。 不幸なことに、UNIX のファイルシステムは「実行可能で読めない」スクリプトを 作る直接の方法が ない。setgid シェルスクリプトをサポートしたシステムでは、 次のようにすることで間接的にシ ミュレートできる。 , Expect スクリプト(機密情報の入った)を普通に作る。 そのパーミッションを 750 (-rwxr-x---) に設定し、trusted group つまり、読んでも良いグループ の所有とする。必要なら、この目的のた めの 新しいグループをつくること。次に、/bin/sh スクリプトを パーミッション 2751 (-rwxr-s--x) で、同じグループの所有で作成する。 こうすると、シェルスクリプトはだれからも実行でき(かつ、読め)る。 実行すると、それは Expect スクリプトを実行する。
関連項目
Tcl(3), libexpect(3) "Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" by Don Libes, pp. 602, ISBN 1-56592-090-2, O'Reilly and Associates, 1995. "expect: Curing Those Uncontrollable Fits of Interactivity" by Don Libes, Proceedings of the Summer 1990 USENIX Conference, Anaheim, California, June 11-15, 1990. "Using expect to Automate System Administration Tasks" by Don Libes, Proceedings of the 1990 USENIX Large Installation Systems Administration Conference, Colorado Springs, Colorado, October 17-19, 1990. "Tcl: An Embeddable Command Language" by John Ousterhout, Proceedings of the Winter 1990 USENIX Conference, Washington, D.C., January 22-26, 1990. "expect: Scripts for Controlling Interactive Programs" by Don Libes, Computing Systems, Vol. 4, No. 2, University of California Press Journals, November 1991. "Regression Testing and Conformance Testing Interactive Programs", by Don Libes, Proceedings of the Summer 1992 USENIX Conference, pp. 135-144, San Antonio, TX, June 12-15, 1992. "Kibitz - Connecting Multiple Interactive Programs Together", by Don Libes, Software - Practice & Experience, John Wiley & Sons, West Sussex, England, Vol. 23, No. 5, May, 1993. "A Debugger for Tcl Applications", by Don Libes, Proceedings of the 1993 Tcl/Tk Workshop, Berkeley, CA, June 10-11, 1993.
著者
Don Libes, National Institute of Standards and Technology
謝辞
Tclを生み出した John Ousterhout と、インスピレーションを与えてくれた Scott Paisley に感謝 する。 Expect のオートコンフィギュレーションコードについて、 Rob Savoye に感謝する。 HISTORY ファイルに expect の進化の大部分が記述されている。このファイルは面白く読めて、か つ、 あなたのこのソフトウェアへの洞察をより深くするだろう。このファイルに 書かれている、私 にバグフィックスを送ってくれた人たちや、他の援助を してくれた人たちに感謝する。 Expect の設計と実装は、部分的にアメリカ政府からその対価をもらっているので、 パブリックドメ インである。しかし、このプログラムとドキュメントあるいは その一部が使われたなら、著者と NIST への謝辞を述べてもらいたい。 29 December 1994 EXPECT(1)