Linux / Unixコマンドの期待

Expectは、スクリプトに従って他の対話型プログラムと会話するプログラムです。 スクリプトに続いて、Expectはプログラムから何が期待できるのか、そして正しい応答が何であるべきかを知っています。 インタプリタ言語は、ダイアログを指示するための分岐および高水準の制御構造を提供します。 さらに、ユーザは、必要なときに制御を行い、直接対話し、その後に制御をスクリプトに戻すことができる。

ExpectkはExpectとTkが混在しています。 ExpectとTkの希望と同じように動作します。 Expectは、TclなしでCまたはC ++で直接使用することもできます。

"Expect"という名前は、uucp、kermit、および他のモデム制御プログラムによって一般化されたsend / expectシーケンスのアイデアから来ています。 しかし、uucpとは異なり、Expectはあらゆるプログラムとタスクを念頭に置いてユーザーレベルのコマンドとして実行できるように一般化されています。 Expectは同時に複数のプログラムと話すことができます。

期待できること

たとえば、expectコマンドでできることは次のとおりです。

シェルがこれらのタスクを実行できないさまざまな理由があります。 すべてはExpectで可能です。

一般に、Expectは、プログラムとユーザーとのやりとりを必要とするプログラムを実行する場合に便利です。 必要なのは、相互作用をプログラム的に特徴付けることだけである。 Expectは、制御されているプログラムを停止させることなく、ユーザーに制御を戻すこともできます。 同様に、ユーザーはいつでもスクリプトに制御を戻すことができます。

使用法

Expectはcmdfileを読み込み、実行するコマンドのリストを取得します。 Expectは#!をサポートするシステム上で暗黙的に呼び出されるかもしれません。 スクリプトを実行可能ファイルとしてマークし、スクリプトの最初の行を作成することにより、

#!/ usr / local / bin / expect -f

もちろん、パスはExpectがどこに住んでいるかを正確に記述する必要があります。 / usr / local / binは単なる例です。

-cフラグは、スクリプト内のanyより前に実行されるコマンドに先行します。 このコマンドは、シェルによって分割されないように引用符で囲む必要があります。 このオプションは複数回使用できます。 複数のコマンドは、セミコロンで区切って-cオプションを付けて実行することができます。 コマンドは表示された順序で実行されます。 Expectkを使用する場合、このオプションは-commandとして指定されます。

-dフラグは、何らかの診断出力を有効にします。これは主にexpectやinteractなどのコマンドの内部動作を報告します。 このフラグは、Expectスクリプトの先頭にある "exp_internal 1"と同じ効果を持ち、Expectのバージョンが出力されます。

-Dフラグは、対話式デバッガーを使用可能にします。 整数値が続くはずです。 デバッガは、値がゼロ以外の場合、または^ Cが押された場合やブレークポイントがヒットした場合、またはスクリプトに他の適切なデバッガコマンドが表示された場合に、次のTclプロシージャの前に制御を受けます。 Expectkを使用する場合、このオプションは- Debugとして指定されます。

-fフラグは、コマンドを読み取る元のファイルに先行します。 #!を使用する場合にのみ便利なので、フラグ自体はオプションです。 他の引数がコマンドラインで提供されるようにします。 Expectkを使用する場合、このオプションは-fileとして指定されます。

デフォルトでは、コマンドファイルはメモリに読み込まれ、その全体が実行されます。 一度に1行ずつファイルを読むことが望ましい場合があります。 このように任意のファイルを強制的に処理するには、-bフラグを使用します。 Expectkを使用する場合、このオプションは-bufferとして指定されます。

文字列 " - "がファイル名として提供された場合は、代わりに標準入力が読み込まれます。 実際に " - "という名前のファイルから読み込むには "./-"を使用します。

-iフラグを指定すると、Expectはファイルから読み込むのではなく対話形式でコマンドを要求します。 プロンプトは、exitコマンドまたはEOFで終了します。 コマンド・ファイルも-cも使用されていない場合は、-iフラグが仮定されます。 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とargという名前の変数に格納されます。 argcはargvの長さに初期化されます。

Argv0は、スクリプトが使用されていない場合、スクリプトまたはバイナリの名前であると定義されています。 たとえば、スクリプトの名前と最初の3つの引数を次のように出力します。

send_user "$ argv0 [lrange $ argv 0 2] \ n"

コマンド

ExpectはTool Command Languageを使用します。 Tclは、制御フロー(if、for、break)、式評価、および再帰やプロシージャ定義などのいくつかの他の機能を提供します。 ここで使用されていても定義されていないコマンド(set、if、exec)はTclコマンドです。 Expectは追加のコマンドをサポートしています。 特に指定しない限り、コマンドは空文字列を返します。

コマンドはアルファベット順にリストされているので、コマンドを素早く見つけることができます。 しかし、新しいユーザーは、spawn、send、expect、およびinteractの説明をこの順番で読むことで、開始が容易になる場合があります。

閉じる[-slave] [-onexec 0 | 1] [-i spawn_id]

現在のプロセスへの接続を閉じます 。 ほとんどのインタラクティブなプログラムは、標準と出口でEOFを検出します。 したがって、通常はプロセスを終了するのにも十分です。 -iフラグは、指定されたspawn_idに対応するプロセスを閉じることを宣言します

expectとinteractは、現在のプロセスが終了して暗黙のうちに終了したことを検出しますが、例えば "exec kill $ pid"というプロセスを終了すると、明示的にcloseを呼び出す必要があります

-onexecフラグは、生成された新しいプロセスでspawn idがクローズされるかどうか、またはプロセスがオーバーレイされるかどうかを決定します。 スポーンIDを開いたままにするには、値0を使用します。ゼロ以外の整数値は、新しいプロセスでスポーンを強制的に閉じます。

-slaveフラグは、spawn idに関連付けられたスレーブを閉じます。 接続が閉じられると、スレーブはまだ開いていれば自動的に閉じられます。

暗黙的または明示的に接続が閉じられているかどうかにかかわらず、waitを呼び出して対応するカーネルプロセススロットをクリアする必要があります。 closeコマンドは、 プロセス接続を閉じることで終了する保証がないため、waitを呼び出さない。

デバッグ[[-now] 0 | 1]

ステートメントをステップ実行してブレークポイントを設定できるようにするTclデバッガーを制御します。

引数がない場合は、デバッガが実行されていない場合は1が返され、それ以外の場合は0が返されます。

1つの引数を指定すると、デバッガが起動します。 引数が0の場合、デバッガは停止します。 1つの引数の前に-nowフラグが指定されていると、デバッガはただちに起動します。 それ以外の場合、デバッガは次のTcl文で起動されます。

debugコマンドはトラップを変更しません。 これを-DフラグでExpectを開始することと比較してください。

切断コマンドは、フォークされたプロセス端末から切断します。 それはバックグラウンドで実行し続けます。 プロセスには独自のプロセスグループが与えられます。 標準I / Oは/ dev / nullにリダイレクトされます

次のフラグメントは、disconnectを使用してバックグラウンドでスクリプトを実行し続けます。

if {[fork]!= 0}切断を終了します。 。 。

次のスクリプトは、パスワードを読み取り、実行するたびにパスワードを要求するプログラムを1時間ごとに実行します。 スクリプトはパスワードを入力するので、一度だけ入力するだけです。

{$ 1} $ {{fork}!= 0}の場合{sleep 3600; continue}スポーンを切断するpriv_prog expectパスワード: "$ expect_out( 1、文字列)\ r " 。 。 出口 }

シェルの非同期処理機能(&)での切断を使用する利点は、切断する前にターミナルパラメータを保存し、後でそれらを新しいptysに適用できることです。 Expectは、Expectが制御を受け取るまでに端末が既に切断されているため、端末のパラメータを読み取る機会はありません。

exit [-opts] [status]

Expectを終了させたり、そうするように準備したりします。

-onexitフラグを指定すると、次の引数が終了ハンドラとして使用されます。 引数がなければ、現在の終了ハンドラが返されます。

-noexitフラグを指定すると、 Expectは終了準備をしますが、実際に制御をオペレーティングシステムに戻すことはできません。 ユーザー定義の終了ハンドラは、Expect自身の内部ハンドラと同様に実行されます。 それ以上のExpectコマンドは実行されません。 Expectを他のTcl拡張で実行している場合に便利です。 現在のインタプリタ(およびTk環境の場合はメインウィンドウ)は、他のTcl拡張がクリーンアップできるように残っています。 Expectのexitが再度呼び出された場合(ただし、これが発生する可能性があります)、ハンドラは再実行されません。

終了すると、生成されたプロセスへのすべての接続が閉じられます。 クローズは、生成されたプロセスによってEOFとして検出されます。 exitは、通常の_exit(2)プロシージャが行う以外のアクションは行いません。 したがって、EOFをチェックしない生成されたプロセスは引き続き実行される可能性があります。 (さまざまな条件は、生成されたプロセスにどのような信号が送られるかを判断するのに重要ですが、システム依存です(通常はexit(3)でドキュメント化されています)。実行を継続する生成プロセスはinitによって継承されます。

status (指定されていない場合は0)がExpectの終了ステータスとして返されます。 スクリプトの終わりに達すると、 exitは暗黙的に実行されます。

exp_continue [-continue_timer]
コマンドexp_continueは、通常通りに戻るのではなく、実行自体を継続することを可能にます。 デフォルトでは、 exp_continueはタイムアウトタイマーをリセットします。 -continue_timerフラグは、タイマーの再起動を防ぎます。 (詳細について期待値を参照てください)。

exp_internal [-fファイル]の値
valueが0以外の場合、 Expectに内部の診断情報をstderrに送るためのさらなるコマンドを生成します。 が0の場合、この出力は無効になります 。診断情報には、受信したすべての文字と、現在の出力をパターンと照合するすべての試行が含まれます。

オプションのファイルが指定されていれば、(値の値にかかわらず)すべての標準出力とデバッグ出力がそのファイルに書き込まれます。 以前の診断出力ファイルは閉じられています。

-infoフラグは、exp_internalに与えられた最新の非情報引数の記述を返します。

exp_open [args] [-i spawn_id]
元のスポーンIDに対応するTclファイル識別子を返します。 ファイル識別子は、Tclのopenコマンドで開かれたかのように使用できます。 (spawn idはもはや使用されるべきではありません。 待機は実行されません。

-leaveopenフラグは、Expectコマンドによるアクセスのためにspawn idを開いたままにします。 waitは、spawn idに対して実行する必要があります。

exp_pid [-i spawn_id]
現在生成されているプロセスに対応するプロセスIDを返します。 -iフラグを使用すると、返されたpidは、指定されたspawn idの戻り値に対応します。

exp_send
sendのエイリアスです。

exp_send_error
send_errorのエイリアスです。

exp_send_log
send_logの別名です。

exp_send_tty
send_ttyのエイリアスです。

exp_send_user
send_userの別名です。

exp_version [[-exit] version]
スクリプトが現在のバージョンのExpectと互換性があることを確認するのに便利です。

引数がなければ、現在のバージョンのExpectが返されます。 このバージョンは、あなたのスクリプトにコード化されるかもしれません。 最近のバージョンの機能を使用していないことが実際に分かっている場合は、以前のバージョンを指定できます。

バージョンはドットで区切られた3つの数字で構成されています。 最初はメジャー番号です。 別のメジャー番号のExpectのバージョン用に書かれたスクリプトはほとんど確実に機能しません。 exp_versionは、メジャー番号が一致しない場合にエラーを返します。

2番目はマイナー番号です。 現在のバージョンよりも大きなマイナー番号を持つバージョン用に作成されたスクリプトは、新しい機能に依存する可能性があり、実行されない可能性があります。 exp_versionは、メジャー番号が一致してもスクリプトのマイナー番号が実行中のExpectの番号より大きい場合にエラーを返します。

3番目は、バージョンの比較に関与しない数字です。 ただし、追加のドキュメントや最適化など、 Expectソフトウェアの配布が何らかの方法で変更された場合は、これが増えます。 新しいマイナーバージョンごとに0にリセットされます。

-exitフラグを指定すると、 Expectはエラーを出力し、バージョンが古くなった場合に終了します。

[[-opts] pat1 body1] ... [-opts] patn [bodyn]を期待する
パターンの1つが生成されたプロセスの出力と一致するか、指定された時間が経過するか、またはファイルの終わりが見えるまで待ちます。 最後のボディが空の場合は、省略することができます。

最新のexpect_beforeコマンドのパターンは、他のパターンの前に暗黙的に使用されます。 最新のexpect_afterコマンドのパターンは、他のパターンの後で暗黙的に使用されます。

expect文全体の引数に複数の行が必要な場合は、各行をバックスラッシュで終了させないように、すべての引数を1つに "補強"することができます。 この1つのケースでは、中括弧にもかかわらず通常のTcl置換が行われます。

パターンがキーワードeofの場合、ファイルの終わりに対応する本文が実行されます。 パターンがキーワードtimeoutの場合、 タイムアウト時に対応する本体が実行されます。 timeoutキーワードを使用しない場合、タイムアウト時に暗黙のヌルアクションが実行されます。 デフォルトのタイムアウト時間は10秒ですが、「set timeout 30」コマンドで30に設定できます。 無限のタイムアウトは値-1で指定することができます。 パターンがキーワードdefaultの場合、対応する本文はタイムアウトまたはファイルの終わりのいずれかで実行されます。

パターンが一致すると、対応する本体が実行されます。 expectは本文の結果を返します(パターンが一致しない場合は空の文字列)。 複数のパターンが一致する場合は、最初に表示されたパターンがボディを選択するために使用されます。

新しい出力が到着するたびに、それは各パターンとリストされた順序で比較されます。 したがって、プロンプトのように、最後のパターンを何かが出現することを保証することによって、一致がないかどうかをテストすることができます。 プロンプトが表示されない場合は、 タイムアウトを使用する必要があります(手動で対話した場合と同じように)。

パターンは3つの方法で指定されます。 デフォルトでは、パターンはTclの文字列一致コマンドで指定されます。 (このようなパターンは、通常、「glob」パターンと呼ばれるCシェルの正規表現にも似ています)。 -glフラグを使用すると、 expectフラグと一致する可能性のあるパターンを保護することができます。 " - "で始まるパターンは、このように保護する必要があります。 ( " - "で始まるすべての文字列は将来のオプション用に予約されています)。

たとえば、次のフラグメントは正常なログインを探します。 ( 中止は、スクリプト内の別の場所で定義されたプロシージャであることに注意してください。)

{ビジー{ビジー\ n; exp_continue}失敗abort "無効なパスワード" abort timeout abort connected}

4番目のパターンには引用符が必要です。スペースが含まれているため、アクションからパターンを分離することになります。 同じアクション(3番目と4番目など)のパターンは、アクションを再度リストする必要があります。 これは、regexp形式のパターンを使用することで回避できます(下記参照)。 グロブスタイルのパターンを形成する方法の詳細は、Tclのマニュアルを参照してください。

正規表現形式のパターンはTclのregexp ( "正規表現"の略)コマンドで定義された構文に従います。 regexpパターンは、フラグ-reとともに導入されます。 前の例はregexpを使って次のように書き直すことができます:

{ビジー{ビジー\ n; exp_continue} -re "無効なパスワード" abort timeout abort connected}

両方のタイプのパターンは「アンカーされていない」。 つまり、パターンは文字列全体に一致する必要はありませんが、文字列内の任意の場所にマッチを開始したり終了したりすることができます。 文字列の先頭に一致するには^を使用し、最後に一致させるには$を使用します。 文字列の終わりを待たない場合、応答は生成されたプロセスからエコーされるので、文字列の途中で簡単に終わる可能性があることに注意してください。 それでも正しい結果が得られれば、出力は不自然に見えます。 したがって、文字列の最後に文字を正確に記述することができれば、$を使用することをお勧めします。

多くのエディタでは、^と$がそれぞれ行頭と終わりに一致することに注意してください。 ただし、expectは行指向ではないため、これらの文字は、現在期待一致バッファ内にある(行ではなく)データの先頭と末尾に一致します。 (また、以下の「システム消化不良」の注記を参照してください)

-exフラグを指定すると、パターンは「正確な」文字列として照合されます。 *、^などは解釈されません(ただし、通常のTcl規​​則はまだ守られていなければなりません)。 正確なパターンは常にアンカーされています。

-nocaseフラグを指定すると、出力の大文字が小文字のように比較されます。 パターンは影響を受けません。

出力を読み込んでいる間に、2000 バイト以上で、以前のバイトを強制的に「忘れてしまいます」。 これはmatch_max関数で変更することができます。 (値が大きすぎるとパターンマッチャーが遅くなる可能性があるので注意してください) 。patlistfull_bufferの場合、 match_maxバイトが受信され、他のパターンは一致しない場合、対応する本体が実行されます。 full_bufferキーワードが使用されているかどうかにかかわらず、忘れられた文字はexpect_out(バッファ)に書き込まれます。

patlistがキーワードnullであり、 nullが( remove_nullsコマンドによって)許可されている場合、単一のASCII 0がマッチする場合、対応する本体が実行されます。 globまたはregexpパターンで0バイトを照合することはできません。

パターン(またはeofまたはfull_buffer)をマッチすると、一致していて以前に一致しなかった出力が変数expect_out(バッファ)に保存されます。 expect_out(9、string)を介してexpect_out( 1、string)変数に最大9個の正規表現の部分文字列一致が保存されます。 パターンの前に-indicesフラグが使用されている場合、10文字列の開始および終了インデックス( lrangeに適した形式)はexpect_out(X、start)およびexpect_out(X、end)変数に格納されます。バッファ内の部分文字列の位置に対応します。 0はパターン全体にマッチしたストリングを指し、globパターンとregexpパターンに対して生成されます。 たとえば、プロセスが "abcdefgh \ n"の出力を生成した場合、次の結果が得られます。

CDを期待する

次のような文が実行されたかのようです。

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

出力バッファには "efgh \ n"が残っています。 プロセスが出力 "abbbabckkka \ n"を生成した場合、次の結果が得られます。

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

次のような文が実行されたかのようです。

(0、文字列)3 expect_out(1、string)3 set expect_out(1、string)bbセットのexpect_out(0、文字列) (2、start)10 set expect_out(2、end)10 expect_out(2、string)kセットexpect_out(バッファ)abbbcabkkkk

出力バッファには "a \ n"が残っています。 パターン "*"(および-re "。*")は、プロセスからの出力をもう読まずに出力バッファをフラッシュします。

通常、一致した出力はExpectの内部バッファから破棄されます。 これは、パターンの前に-notransferフラグを付けることで防ぐことができます。 このフラグは、実験で特に便利です(実験中は便宜上「 - なし」と省略できます)。

一致する出力(またはeofまたはfull_buffer)に関連付けられたspawn idは、 expect_out(spawn_id)に格納されます。

-timeoutフラグを指定すると、現在のexpectコマンドは、timeout変数の値を使用する代わりに、次の値をタイムアウトとして使用します。

デフォルトでは、パターンは現在のプロセスの出力と一致しますが、 -iフラグは指定されたspawn_idリストからの出力を次のパターン(次の-iまで )と照合することを宣言します。 spawn_idリストは、空白で区切られたspawn_idのリストか、そのようなspawn_idsのリストを参照する変数のいずれかでなければなりません。

たとえば、次の例では、現在のプロセスから "connected"、または$ proc2で指定されたspawn_idから "busy"、 "failed"または "invalid password"を待ちます。

{-i $ proc2 busy {puts busy \ n; exp_continue} -re "無効なパスワード" abort timeout abort connected}

グローバル変数any_spawn_idの値は、現在のexpectコマンドで他のすべての-iフラグで指定されたspawn_idにパターンを一致させるために使用できます。 関連するパターンのない-iフラグからのspawn_idは、any_spawn_idに関連付けられた同じexpectコマンド内の他のパタ​​ーンで使用可能になります

-iフラグは、グローバル変数に名前をつけることもできます。この場合、変数はスポーンIDのリストのために読み込まれます。 変数は変更されるたびに再度読み込まれます。 これにより、コマンドの実行中にI / Oソースを変更する方法が提供されます。 このように提供されたスポーンIDは、「間接」スポーンIDと呼ばれます。

breakcontinueなどのアクション 、制御構造(つまり、 forproc )が通常の方法で動作するようにします。 コマンドexp_continueは、通常通りに戻るのではなく、実行自体を継続することを可能にます。

これは、明示的なループや繰り返しのexpect文を避けるのに便利です。 以下の例は、rloginを自動化するための断片の一部です。 exp_continueは、rloginがパスワードの入力を求めた場合に2番目のexpect文(プロンプトをもう一度探すため)を書く必要がありません

$ hostに "{stty -echo send_user"}パスワードを入れてください: "expect_user -re"(。*)\ n "send_user" \ n "send" $ expect_out(1、string)\ r "sttyホストへの接続に失敗しました:$ expect_out(バッファ) "exit} - ホストへの接続が失敗しました\ n" re $ prompt}

たとえば、次の部分は、すでに完全に自動化された操作をユーザーがガイドするのに役立ちます。 この場合、端末はrawモードになります。 ユーザーが "+"を押すと、変数がインクリメントされます。 "p"を押すと、いくつかの戻り値がプロセスに送られ、何らかの方法でそれを突き止めることができます。 "i"はプロセスと対話し、スクリプトから制御を奪ってしまいます。 いずれの場合も、 exp_continueは、現在のアクションの実行後に現在のパターンマッチングを継続すること期待しています。

stty raw -echo expect_after {-i $ user_spawn_id "p" {"\ r \ r \ r"; exp_continue} "+" {incr foo; exp_continue} "i" {interact; exp_continue} "終了"}

デフォルトでは、 exp_continueはタイムアウトタイマーをリセットします。 -continue_timerフラグを指定してexp_continueを呼び出すと、タイマーは再起動されません。

expect_after [expect_args]
expect_beforeと全く同じように動作しますが、 expectexpect_afterのパターンが一致する場合、 expectパターンが使用されます。 詳細については、 expect_beforeコマンドを参照してください。

expect_background [expect_args]
expectと同じ引数をとりますが、すぐに戻ります。 新しい入力が到着するたびにパターンがテストされます。 パターンのタイムアウトデフォルトexpect_backgroundにとって無意味であり、黙って破棄されます。 それ以外の場合、 expect_backgroundコマンドはexpect同様に expect_beforeexpect_afterパターンを使用します。

expect_backgroundアクションが評価されているとき、同じスポーンidのバックグラウンド処理はブロックされます。 アクションが完了すると、バックグラウンド処理はブロック解除されます。 バックグラウンド処理がブロックされている間は、同じスポーンIDに対して(フォアグラウンド) expectを実行することは可能です。

expect_backgroundアンブロックされているは、 expectを実行することはできません。 特定のスポーンIDのexpect_backgroundは、同じスポーンIDを持つ新しいexpect_backgroundを宣言することによって削除されます。 パターンなしでexpect_backgroundを宣言すると、与えられたスポーンIDがバックグラウンドでパターンにマッチする能力から削除されます。

expect_before [expect_args]
expectと同じ引数をとりますが、すぐに戻ります。 同じspawn idを持つ最新のexpect_beforeからのパターンアクションペアは、後続のexpectコマンドに暗黙的に追加されます。 パターンが一致すると、それはexpectコマンド自体で指定されたものとして扱われ、関連する本体はexpectコマンドのコンテキストで実行されます。 expect_beforeexpectの両方のパターンが一致する場合は、 expect_beforeパターンが使用されます。

パターンが指定されていない場合、スポーンidはどのパターンでもチェックされません。

-iフラグでオーバーライドされない限り、 expect_beforeパターンは、 expect_beforeコマンドが実行された時点で定義されたスポーンidと一致します(パターンが一致している場合ではありません)。

-infoフラグを指定すると、 expect_beforeは一致するパターンの現在の指定を返します。 デフォルトでは、現在のスポーンIDを報告します。 オプションで、spawn idに関する情報を指定することができます。 例えば

expect_before -info -i $ proc

多くの場合、1つのspawn id指定が与えられます。 フラグ-indirectは、間接的な指定のみから来る直接スポーンIDを抑制します。

スポーンID仕様の代わりに、フラグ "-all"を指定すると、すべてのスポーンIDについて "-info"がレポートされます。

-infoフラグの出力は、expect_beforeの引数として再利用できます。

expect_tty [expect_args]
expectと同じですが、/ dev / ttyから文字を読み込みます(つまり、ユーザからのキーストローク)。 デフォルトでは、読み取りはcookedモードで実行されます。 したがって、行はそれらを見ることを期待するためにリターンで終わらなければなりません。 これはsttyによって変更される可能性があります(下記のsttyコマンドを参照してください)。

expect_user [expect_args]
期待通りですが、標準入力から文字を読み込みます(ユーザーからのキーストローク)。 デフォルトでは、読み取りはcookedモードで実行されます。 したがって、行はそれらを見ることを期待するためにリターンで終わらなければなりません。 これはsttyによって変更される可能性があります(下記のsttyコマンドを参照してください)。

フォーク
新しいプロセスを作成します 。 新しいプロセスは、現在のExpect プロセスの正確なコピーです。 成功すると、 forkは0を新しい(子プロセス )に返し、子プロセスの プロセス IDを親プロセスに返します 。 失敗した場合(常にスワップ領域、メモリなどのリソースが不足しているため)、 forkは親プロセスに -1を返し、子プロセスは作成されません。

フォークされたプロセスは、元のプロセスと同様に、 exitコマンドによって終了します 。 フォークされたプロセスはログファイルに書き込むことができます。 ほとんどのプロセスでデバッグやロギングを無効にしないと、結果が混乱する可能性があります。

いくつかのptyの実装は、一瞬でも複数の読者や作家によって混乱するかもしれません。 したがって、産卵プロセスの前にフォークするのが最も安全です。

interact [string1 body1] ... [stringn [bodyn]]
現在のプロセスをユーザーに制御し、キーストロークが現在のプロセスに送信され、現在のプロセスのstdoutとstderrが返されます。

文字列と本体のペアを引数として指定できます。この場合、対応する文字列が入力されたときに本体が実行されます。 (デフォルトでは、文字列は現在のプロセスには送信されません)。最後のボディがない場合は、 interpreterコマンドが仮定されます。

対話文全体への引数に複数の行が必要な場合は、各行をバックスラッシュで終了させないように、すべての引数を1つに "ブレース"することができます。 この1つのケースでは、中括弧にもかかわらず通常のTcl置換が行われます。

たとえば、以下のコマンド実行は、定義された以下の文字列 - 本体ペアと対話します。^ Zが押されると、 Expectは一時停止されます。 ( -resetフラグは端末モードを復元します)。^ Aが押されると、ユーザーは「あなたが入力した制御A」と見なされプロセスは^ Aに送られます。 $を押すと、ユーザーに日付が表示されます。 ^ Cを押すと、 Expectが終了します。 「foo」が入力された場合、ユーザは「bar」を見る。 ~~を押すと、 Expectインタプリタが対話的に実行されます。

CTRLZ \ 032を設定します。{-reset $ CTRLZ {exec kill -STOP [pid]} \ 001 {send_user "あなたが入力したコントロール-A \ n"; "\ 001"} $ {send_user "日付は[時計の形式[クロック秒]]です。"} \ 003 exit foo {send_user "bar"} ~~}

文字列と本体のペアでは、文字列は引数としてリストされた順にマッチします。 部分的に一致する文字列は、残りの部分が来ることを予期して現在のプロセスに送られません。 文字が一致する可能性がなくなるように文字が入力された場合、文字列の一部のみが別の一致を開始できないプロセスに送信されます。 したがって、最終的に一致しようとしていた元の文字列が失敗した場合、部分一致の部分文字列である文字列が後で一致する可能性があります。

デフォルトでは、文字列の一致はワイルドカードなしのものです。 これとは対照的に、 expectコマンドはデフォルトでglobスタイルのパターンを使用します。- exフラグを使用すると、 対話フラグに一致する可能性のあるパターンを保護できます。 " - "で始まるパターンは、このように保護する必要があります。 ( " - "で始まるすべての文字列は将来のオプション用に予約されています)。

-reフラグを指定すると、文字列は正規表現形式のパターンとして解釈されます。 この場合、一致する部分文字列はexpect_out変数にexpectが格納される方法同様にinteract_out変数に格納されます。 -indicesフラグも同様にサポートされています。

パターンeofは、ファイルの終わりに実行されるアクションを導入します。 別のeofパターンが-outputフラグの後に続く場合もあります。この場合、出力の書き込み中にeofが検出された場合は一致します。 デフォルトのeofアクションは "return"なので、 interactは単にEOFを返します。

パターンのタイムアウトは、タイムアウト(秒)と、指定された時間文字が読み込まれなかった後に実行されるアクションを導入します。 タイムアウトパターンは、最後に指定されたプロセスに適用されます 。 デフォルトのタイムアウトはありません。 特別な変数 "timeout"( expectコマンドによって使用される)は、このタイムアウトに影響しません。

たとえば、次の文を使用して、何も入力していないが、システムメッセージを頻繁に取得しているユーザーを自動ログアウトすることができます。

interact -input $ user_spawn_idタイムアウト3600 return -output \ $ spawn_id

パターンがキーワードnullであり、 nullが( remove_nullsコマンドによって)許可されている場合、単一のASCII 0がマッチした場合、対応する本体が実行されます。 globまたはregexpパターンで0バイトを照合することはできません。

パターンの先頭にフラグを立てると、変数interact_out(spawn_id)がパターン(またはeof)に一致するspawn_idに設定されます。

breakcontinueなどのアクション 、制御構造(つまり、 forproc )が通常の方法で動作するようにします。 しかし、 inter_return対話を引き起こして呼び出し元で戻り値を返す間に、戻りは対話を呼び出し元に返します。 たとえば、 "proc foo"がinteract呼び出してinter_returnアクションを実行した場合proc fooが戻ります。 これは、 インタラクティブ・インタラクティブ・インタラクティブ・コール・インタラクティブ・コール・インタラクティブ・インタラクション・コール・インタラクション

対話中には、すべての文字が現在のプロセスに渡されるようにrawモードが使用されます 。 現在のプロセスがジョブ制御信号を捕捉しない場合は、停止信号(デフォルトでは^ Z)が送信されると停止します。 それを再起動するには、continueシグナルを送信します( "kill-CONT"など)。 あなたが本当にそのようなプロセス (^ Zによる)にSIGSTOPを送る場合は、まずcshを生成してからプログラムを実行することを検討してください。 一方、SIGSTOPをExpectに送る場合は、まずインタープリターを呼び出し(おそらくエスケープ文字を使用して)、^ Zを押します。

文字列と本体のペアは、インタプリタを入力して対話的にコマンドを実行する必要を回避するための略語として使用できます。 以前の端末モードは、文字列 - 本体対の本体が実行されている間に使用されます。

速度に関しては、アクションはデフォルトでrawモードで実行されます。 -resetフラグは、 対話が実行される前のモード(常に、cookedモード)にターミナルをリセットします。 モードの切り替え時に入力される文字は失われる可能性があることに注意してください(一部のシステムではターミナル・ドライバーの残念な機能です)。 -resetを使用する唯一の理由は、動作が調理モードで実行されているかどうかによって決まります。

-echoフラグは、次のパターンに一致する文字を、それぞれの文字が読み込まれるときに生成されたプロセスに戻します。 これは、ユーザーが部分的に入力されたパターンからのフィードバックを参照する必要がある場合に便利です。

パターンがエコーされているが最終的に一致しない場合、文字は生成されたプロセスに送信されます 。 生成されたプロセスがそれらをエコーすると、ユーザーはその文字を2回見ます。 -echoはおそらく、ユーザーがパターンを完了しそうにない状況でのみ適切です。 たとえば、次の抜粋は、現在のディレクトリを再帰的に取得、入力、または一覧表示するために〜g、〜pまたは〜lを入力するようユーザーにプロンプ​​トが出されるrftpの再帰的-ftpスクリプトからの抜粋です。 これらは通常のftpコマンドとはかなり離れているため、間違いを除いて〜と入力することはまずありません。その場合は、とにかく結果を無視することになります。

対話{-echo〜g {getcurdirectory 1} -echo〜l {getcurdirectory 0} -echo〜p {putcurdirectory}}

-nobufferフラグは、次のパターンと一致する文字を、文字が読み込まれるときに出力プロセスに送ります。

これは、プログラムがパターンをエコーバックさせたい場合に便利です。 たとえば、次のようにして、人がどこにダイヤルしているかを監視することができます(Hayesスタイルのモデム)。 "atd"が表示されるたびに、スクリプトは残りの行を記録します。

proc lognumber {} {対話型--nobuffer -re "(。*)\ r"戻り値$ log "[時計式[クロック秒]]:ダイヤル$ interact_out(1、string)"}対話型 - バッファー "atd" lognumber

対話中に、以前のlog_userの使用は無視されます。 特に、 対話は、ユーザが盲目的に対話したくないと推定されるので、その出力をログに記録する(標準出力に送信する)。

-oフラグを指定すると、現在のプロセスの出力に、後続のキーとボディのペアが適用されます 。 これは、たとえば、telnetセッション中に不要な文字を送信するホストを扱う場合に便利です。

デフォルトでは、 interactはユーザーがstdinを書き、 Expect プロセス自体のstdoutを読み込むことを期待してい ます-uフラグ( "user"の場合)は、ユーザーのインタラクションを、その引数で指定されたプロセス (スポーンされたIDでなければならない)として見ます。

これにより、明示的なループを使用せずに、関係のない2つのプロセスを結合することができます。 デバッグを助けるために、Expect診断は常にstderr(または特定のロギングとデバッグ情報についてはstdout)に行きます。 同じ理由で、 インタプリタコマンドはstdinから対話的に読み込まれます。

たとえば、次のフラグメントはログインプロセスを作成します。 次に、ユーザ(図示せず)にダイヤルし、最後に2つを一緒に接続する。 もちろん、ログインの代わりに任意のプロセスを使用することもできます。 たとえば、シェルを使用すると、アカウントとパスワードを入力せずに作業することができます。

spawn login set login $ spawn_id spawn tip modem#ユーザにダイヤルアウトする#ユーザをloginに接続するinteract -u $ login

出力を複数のプロセスに送信するには、 -outputフラグで始まる各スポーンIDリストをリストします。 出力スポーンIDのグループに対する入力は、入力フラグが前に付いたスポーンIDリストによって決定される。 ( -input-outputの両方が、 expectコマンドの-iフラグと同じ形式でリストを取るかもしれませんが、any_spawn_idは対話では意味がありません)。次のすべてのフラグと文字列 (またはパターン)は、入力フラグが表示されます。 -inputが表示されない場合、 -outputは "-input $ user_spawn_id -output"を意味します。 (同様に、 -inputを持たないパターンの場合)1つの-inputが指定されている場合、$ user_spawn_idは無効になります。 2番目の入力が指定された場合、$ spawn_idは無効になります。 追加の入力フラグを指定することができます。

2つの暗黙の入力プロセスのデフォルトは、出力が$ spawn_idと$ user_spawn_id(逆)に指定されています。 -inputフラグが-outputフラグなしで出現すると、そのプロセスの文字は破棄されます。

-iフラグは、他の-inputまたは-outputフラグが使用されていないときに、現在のspawn_idの置換を導入します。 A -iフラグは-oフラグを意味します。

間接的なスポーンIDを使用して相互作用しているプロセスを変更することは可能です。 (間接的なスポーンidについては、expectコマンドのセクションで説明しています)。間接的なspawn idは、-i、-u、-input、または-outputフラグで指定できます。

インタープリタ[args]
ユーザーにExpectおよびTclコマンドの対話式プロンプトが表示されます。 各コマンドの結果が表示されます。

breakcontinueなどのアクション 、制御構造(つまり、 forproc )が通常の方法で動作するようにします。 しかし、 returnはインタプリタを呼び出し元に戻し、 inter_returnインタプリタを呼び出し元に返します。 たとえば、 "proc foo"がインタープリタ呼び出してinter_returnアクションを実行した場合proc fooが返されます。 他のコマンドを実行すると、 インタプリタは新しいコマンドの入力を続行します。

デフォルトでは、プロンプトには2つの整数が含まれています。 最初の整数は、評価スタックの深さ(つまり、Tcl_Evalが何回呼び出されたか)を表します。 2番目の整数はTcl履歴識別子です。 プロンプトは、 "prompt1"というプロシージャを定義し、戻り値が次のプロンプトになるように設定することができます。 文に開かれた引用符、括弧、中括弧、または角括弧がある場合、改行時に二次プロンプト(デフォルトでは "+>")が発行されます。 セカンダリプロンプトは、 "prompt2"というプロシージャを定義することで設定できます。

インタプリタの実行中に、呼び出し元がrawモードを使用していたとしても、cookedモードが使用されます。

stdinがクローズされている場合、 -eofフラグを使用しない限りインタープリターが戻ります。この場合、後続の引き数が呼び出されます。

log_file [args] [[-a] file]
ファイル名が指定された場合、 log_fileはそのファイルの(その時点で始まる)セッションの写しをファイルに記録します。 引数が指定されない場合、 log_fileは記録を停止します。 以前のログファイルは閉じられています。

ファイル名の代わりに、 -openまたは-leaveopenフラグを使用してTclファイル識別子を提供することができます。 これはspawnコマンドに似ています 。 (詳細については、 spawnを参照してください)。

-aフラグは、 log_userコマンドによって抑制された出力を強制的にログに記録します。

デフォルトでは、 log_fileコマンド 、1つのセッションで複数回ログオフとオフを切り替えることができるように、古いファイルを切り捨てるのではなく、古いファイルに追加します。 ファイルを切り捨てるには、 -noappendフラグを使用します。

-infoフラグは、log_fileに与えられた最新の非情報引数の記述を返します。

log_user -info | 0 | 1
デフォルトでは、send / expectダイアログはstdout(および開いている場合はログファイル)に記録されます。 stdoutへのロギングは、コマンド "log_user 0"によって無効にされ、 "log_user 1"によって再び有効にされます。 ログファイルへのロギングは変更されません。

-infoフラグを指定すると、log_userは指定された最新の非情報引数の説明を返します。

match_max [-d] [-i spawn_id] [size]
expectによって内部的に使用されるバッファのサイズをバイト単位で定義します。 引数なしの場合、現在のサイズが返されます。

-dフラグを指定すると、デフォルトのサイズが設定されます。 (初期のデフォルトは2000です。)- iフラグを指定すると、指定されたspawn idのサイズが設定されます 。それ以外の場合は、現在のプロセスに設定されます

オーバーレイ[ - #spawn_id] [ - #spawn_id] [...]プログラム[args]
終了する現在のExpectプログラムの代わりに"program args"を実行します。 裸のハイフン引数は、ログインシェルであるかのように、コマンド名の前にハイフンを強制します。 すべてのspawn_idは、引数として指定されたものを除いて閉じられます。 これらは、指定されたファイル識別子にマップされます。

Spawn_idは、新しいプログラムが継承するファイル識別子にマップされます。 たとえば、次の行はチェスを実行し、現在のプロセス(チェスマスターなど)によって制御されます。

オーバーレイ-0 $ spawn_id -1 $ spawn_id -2 $ spawn_idチェス

これは "interact -u"よりも効率的ですが、 Expect プロセスがもはや制御されていないため、プログラミングされた対話を行う能力が犠牲になります。

制御端末は設けられていないことに留意されたい。 したがって、標準入力を切断または再マップすると、ジョブ制御(シェル、ログインなど)を行うプログラムは正しく機能しません。

パリティ[-d] [-i spawn_id] [値]
パリティが生成されたプロセスの出力から保持されるか、または取り除かれるべきかを定義します。 が0の場合、パリティは削除されます。そうでない場合は、削除されません。 値の引数がない場合 、現在の値が返されます。

-dフラグを指定すると、デフォルトのパリティ値が設定されます。 -iフラグを指定すると、指定されたspawn idに対してパリティ値が設定されます 。それ以外の場合は、現在のプロセスに設定されます 。デフォルト値は1です。つまり、パリティは削除されません。

remove_nulls [-d] [-i spawn_id] [value]
変数がexpect_outまたはinteract_outに格納される前に、生成されたプロセスの出力からヌルが保持されるか削除されるかを定義します。 が1の場合、NULLは削除されます。 が0の場合、nullは削除されません。 値の引数がない場合 、現在の値が返されます。

-dフラグを指定すると、デフォルト値が設定されます。 (初期のデフォルトは1です。つまり、nullは削除されます) 。-iフラグを指定すると、指定されたspawn idに値が設定されます 。それ以外の場合は、現在のプロセスに設定されます

nullが削除されるかどうかにかかわらず、 Expectはnullバイトをログとstdoutに記録します。

send [-flags] string
文字列を現在のプロセスに送信します 。 たとえば、コマンド

"hello world \ r"を送る

helloworldという文字を現在のプロセスに送ります 。 (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デバイスを参照する場合にのみ意味があります。 ヒントなどのプロセスを生成した場合は、ヒントを生成するためのヒントの規約を使用する必要があります。

-sフラグを指定すると、出力が「ゆっくり」送信されます。そのため、同じバッファをアウトタイプすることのない人間のために設計された入力バッファをコンピュータがアウトタイプ化する一般的な状況を回避できます。 この出力は、2つの要素リストを取る変数 "send_slow"の値によって制御されます。 最初の要素は、原子的に送信するバイト数を表す整数です。 2番目の要素は、アトミックセンドを分離する必要がある秒数を表す実数です。 たとえば、 "send_slow {10 .001}"を設定すると、送信された10文字の間に1ミリ秒の文字列が送信されます。

-hフラグは、人が実際に入力するように出力を送信するようにします(多少)。 文字の間に人間のような遅れが現れます。 (このアルゴリズムは、ワイブル分布に基づいており、この特定のアプリケーションに合わせて変更されています)。この出力は、変数「send_human」の値によって制御され、5つの要素リストを取ります。 最初の2つの要素は、文字の平均到着時間(秒)です。 最初はデフォルトで使用されます。 2番目は単語の終わりで使用され、そのような遷移でときどき発生する微妙な一時停止をシミュレートします。 第3のパラメータは、.1が非常に可変であり、1が合理的に可変であり、10が全く変わらない可変性の尺度である。 極値は0〜無限大です。 最後の2つのパラメータは、それぞれ最小および最大到着時間である。 最小値と最大値が最後に使用され、最後の時刻が「クリップ」になります。 最小値と最大値で十分な値が得られれば、究極の平均値は与えられた平均値と大きく異なることがあります。

一例として、以下のコマンドは速く一貫したタイピストをエミュレートします:

set send_human {.1 .3 1 .05 2} send -h "私は空腹です。ランチをやりましょう。"

一方、二日酔いの後には、以下の方が適しています。

set send_human {.4 .4 .2 .5 100} send -h "グッドパーティーラッシュナイト!"

送信引数に間違いや訂正を埋め込むことで、エラー訂正の状況を自分で設定することはできますが、エラーはシミュレートされません。

ヌル文字の送信、ブレークの送信、遅い出力の強制、ヒューマン・スタイル出力のフラグは相互に排他的です。 最後に指定されたものだけが使用されます。 さらに、ヌル文字またはブレークを送信するためのフラグとともに、 文字列引数を指定することはできません。

最初の送信プロセスに先行させることを期待するのは良い考えです。 プロセスが開始するのを待っていますが、 送信はできません。 特に、 プロセスの実行が開始される前に最初の送信が完了すると、データが無視されるリスクがあります。 対話型プログラムが最初のプロンプトを表示しない状況では、次のような遅延で送信することができます。

#侵入する方法をハッカーに知らせるのを避けるために、このシステムは外部パスワードを要求しません。 #execがspawn telnetを完了するまで5秒待つvery.secure.gov sleep 5パスワードを送信する\ r

exp_sendsendのエイリアスです ExpectkやTk環境でExpectの他の変種を使用している場合、 sendはTkによってまったく異なる目的のために定義されます。 exp_sendは環境間の互換性のために用意されています。 他のExpectの他のsendコマンドにも同様のエイリアスが用意されています。

send_error [-flags]文字列
出力は現在のプロセスではなくstderrに送られる点を除いてsendと似ています

send_log [ - ]文字列
文字列がログファイルにのみ送られることを除いて、 sendと似ています( log_file参照)。ログファイルが開いていなければ、引数は無視されます。

send_tty [-flags]文字列
出力は現在のプロセスではなく/ dev / ttyに 送信されることを除いて、 sendと似ています

send_user [-flags]文字列
出力は現在のプロセスではなくstdoutに送られる点を除いてsendと似ています

睡眠秒
スクリプトを指定された秒数だけスリープさせます。 秒は10進数です。 Expectを使用している場合はInterrupt(およびTkイベント)はExpectがスリープしている間に処理されます。

spawn [args] program [args]
"program args"を実行する新しいプロセスを作成します。 そのstdin、stdout、stderrはExpectに接続されているため、他のExpectコマンドで読み書きすることができます。 接続が終了するか、 プロセス自体がファイル識別子のいずれかを閉じると、接続が切断されます。

プロセスspawnによって開始されると、変数spawn_idはそのプロセスを参照する記述子に設定されますspawn_idで記述されたプロセスは、 「現在の プロセス 」とみなされますspawn_idは読み取りまたは書き込みが可能で、実際にジョブ制御を提供します。

user_spawn_idは、ユーザーを参照する記述子を含むグローバル変数です。 たとえば、 spawn_idがこの値に設定されている場合、 expectexpect_userのように動作します。

.I error_spawn_idは、標準エラーを参照する記述子を含むグローバル変数です。 たとえば、 spawn_idがこの値に設定されている場合、 sendsend_errorのように動作します。

tty_spawn_idは、/ dev / ttyを参照する記述子を含むグローバル変数です。 / dev / ttyが存在しない場合(cron、at、またはbatchスクリプトなど)、 tty_spawn_idは定義されません。 これは次のようにテストされます:

もし#{dev / ttyが存在しない}#{dev / ttyが存在しない}#おそらくcron、バッチ、またはスクリプト}

spawnはUNIXのプロセス IDを返します。 プロセスが生成されない場合、0が返されます。 変数spawn_out(slave、name)は、ptyスレーブデバイスの名前に設定されます。

デフォルトでは、 spawnはコマンド名と引数をエコーし​​ます。 -noechoフラグは、 spawnがこれをやめるのを止めます

-consoleフラグを指定すると、コンソール出力が生成されたプロセスにリダイレクトされます 。 これはすべてのシステムでサポートされているわけではありません。

内部的には、 spawnはptyを使用し、ユーザーのttyと同じ方法で初期化されます。 これはさらにすべての設定が「sane」(stty(1)に従う)になるように初期化されます。 変数stty_initが定義されている場合、stty引数のスタイルで解釈されます。 たとえば、 "set stty_init raw"は、生成されたプロセスの端末がrawモードで起動するようにします。 -nottycopyは、ユーザーのttyに基づいて初期化をスキップします。 -nottyinitは "sane"初期化をスキップします。

通常、 スポーンは実行に少し時間がかかります。 あなたがかなりの時間を取って産卵したことに気がついたら、おそらくptysに遭遇しているでしょう。 誤ったプロセスでの絡み合いを避けるために、ptysで多数のテストが実行されます。 (これらは楔形のptyあたり10秒かかる) -dオプションを指定してExpectを実行すると、 Expectが奇妙な状態で多くのptysに遭遇しているかどうかが示されます。 これらのptysが接続されているプロセスを強制終了できない場合は、再起動する必要があります。

exec(2)が失敗したため(例えばプログラムが存在しないときなど)、 プログラムが正常に生成されない場合、次のinteractまたはexpectコマンドによってエラーメッセージが返され、 プログラムが実行され、出力としてエラーメッセージが生成される。 この動作は、 スポーンの実装の自然な結果です。 内部的には、フォークを生成します。その後、生成されたプロセスは、spawn_idを介した通信を除いて元のExpect プロセスと通信する方法がありません。

-openフラグは、次の引数をTclファイル識別子(すなわち、 openによって返される)として解釈させます。その後、spawnされたプロセスがあたかもspawnされたプロセスであるかのように使用されます 。 (ファイル識別子はもはや使用されるべきではありません)。これにより、ptyを使用せずに生のデバイス、ファイル、パイプラインを生成されたプロセスとして扱うことができます。 関連するプロセスがないことを示すために0が返されます。 生成されたプロセスへの接続が閉じられると、Tclファイルの識別子も閉じます。 -leaveopenフラグは-openと似ていますが、 -leaveopenを指定すると、spawn idがクローズされた後でもファイル識別子が開いたままになります。

-ptyフラグを指定すると、ptyはオープンされますが、 プロセスは生成されません。 関連するプロセスがないことを示すために0が返されます。 通常どおりSpawn_idが設定されます。

変数spawn_out(slave、fd)は、ptyスレーブに対応するファイル識別子に設定される。 これは "close -slave"を使用して閉じることができます。

-ignoreフラグは、生成されたプロセスで無視されるシグナルを指定し ます 。 それ以外の場合は、シグナルがデフォルトの動作になります。 信号は、各信号が別々のフラグを必要とすることを除いて、 trapコマンドの場合と同じ名前です。

straceレベル
実行される前に次のステートメントを出力します。 (Tclのtraceコマンドは変数をトレースします。) levelは、トレースするコールスタックのどれくらい下にあるかを示します。 たとえば、次のコマンドは、最初の4レベルのコールをトレースしながらExpectを実行しますが、それ以下のコールはトレースしません。

-c "strace 4" script.expを期待する

-infoフラグは、straceに与えられた最新の非情報引数の記述を返します。

stty args
外部sttyコマンドと同様に端末モードを変更します。

デフォルトでは、制御端末にアクセスします。 その他の端末には、「コマンドの結果として返されるステータス要求」を追加することでアクセスできます。ステータスが要求されず、制御端末がアクセスされた場合、raw属性とecho属性の以前のステータスは、コマンドで使用されます。

たとえば、引数rawまたは-cookedは端末をrawモードにします。 引数-rawまたはcookedは、端末をcookedモードにします。 引数echo-echoは、端末をエコーモードとノエッチモードにそれぞれ置きます。

次の例は、エコーを一時的に無効にする方法を示しています。 パスワードの埋め込みを避けるために、これ以外の自動スクリプトでも使用できます。 (これについてのより多くの議論を以下のヒントを見てください。)

stty -echo send_user "パスワード:" expect_user -re "(。*)\ n" set password $ expect_out(1、string)stty echo

システム引数
ターミナルからコマンドとして入力されたかのように、sh(1)に入力としてargを与えます。 Expectは、シェルが終了するまで待ちます。 shの戻り状態は、 execが戻り状態を処理するのと同じ方法で処理されます。

stdinとstdoutをスクリプトにリダイレクトするexecとは対照的に、 システムはリダイレクトを実行しません(文字列自体で示されたものを除く)。 したがって、/ dev / ttyと直接話さなければならないプログラムを使用することは可能です。 同じ理由で、 システムの結果はログに記録されません。

タイムスタンプ[args]
タイムスタンプを返します。 引数がなければ、エポックが返されてからの秒数が返されます。

-formatフラグは、返された文字列を導入しますが、置換はstrftimeのPOSIX規則に従って行われます。 たとえば、%aは短縮された曜日の名前(Sat)に置き換えられます。 その他は:

%a短縮された曜日の名前%完全な曜日の名前%b省略された月の名前%B完全な月の名前%c日付の時刻:Oct 10 6 11:45:56 1993年の%d日(01-31%H時間(00〜23)%1時間(01〜12)%j日(001〜366)%m月(01〜12)%M分(00〜59)%p amまたはpm%最初の日曜日は1週目の最初の日です。%V週(01〜53、ISO 8601スタイル)%w day(0〜 6)%W週間(00-53、最初の月曜日は1週目の最初の日)%x日付時刻:Oct 10 6 1993%X時刻:23:59:59%y年(00-99) 1993年のZタイムゾーン(または、決定できない場合は何もありません)%%裸のパーセント記号

その他の%指定は未定義です。 他の文字はそのまま渡されます。 Cロケールのみがサポートされています。

-secondsフラグは、フォーマット元のエポックが使用されてからの秒数を示します。 それ以外の場合は、現在の時刻が使用されます。

-gmtフラグは、タイムスタンプ出力にGMTタイムゾーンを使用させます。 フラグがない場合は、ローカルタイムゾーンが使用されます。

トラップ[[コマンド]信号]
与えられたコマンドのうちのいずれかの将来の受信時に、与えられたコマンドを実行させる。 コマンドはグローバルスコープで実行されます。 commandが指定されていない場合、シグナルアクションが返されます。 commandが文字列SIG_IGNの場合、シグナルは無視されます。 commandが文字列SIG_DFLの場合、シグナルはシステムのデフォルト値になります。 信号は、単一の信号または信号のリストのいずれかです。 信号は、signal(3)のように数値的または象徴的に指定できます。 "SIG"接頭辞は省略することができます。

引数なし(または引数-number)の場合、 trapは現在実行中のtrapコマンドのシグナル番号を返します。

-codeフラグは、コマンドが最初に実行を開始したときにTclが返そうとしていたコードの代わりに、コマンドの戻りコードを使用します。

-interpフラグを指定すると、トラップが宣言されたときではなく、コマンドの実行が開始された時点でインタープリタをアクティブにして、コマンドを評価します。

-nameフラグを指定すると、trapコマンドは現在実行中のtrapコマンドのシグナル名を戻します。

-maxフラグを指定すると、 trapコマンドは設定可能な最大のシグナル番号を戻します。

たとえば、 "trap {send_user" Ouch! "} SIGINT"というコマンドは、 "Ouch!"と表示します。 ユーザが^ Cを押す度に

デフォルトでは、SIGINT(通常は^ Cを押して生成できます)とSIGTERMはExpectを終了させます。 これはExpectが起動したときにデフォルトで作成される以下のトラップによるものです。

トラップ出口{SIGINT SIGTERM}

-Dフラグを使用してデバッガを起動すると、対話型デバッガを起動するためにSIGINTが再定義されます。 これは以下のトラップによるものです。

trap {exp_debug 1} SIGINT

デバッガトラップは、環境変数EXPECT_DEBUG_INITを新しいトラップコマンドに設定することによって変更できます。

もちろん、トラップコマンドをスクリプトに追加するだけで、これらの両方を上書きすることができます。 特に、あなた自身の "trap exit SIGINT"があれば、これはデバッガのトラップより優先されます。 これは、ユーザーがデバッガにまったくアクセスできないようにする場合に便利です。

SIGINTに独自のトラップを定義したいが、実行中にデバッガに依然としてトラップしたい場合は、次のようにしてください:

if {![exp_debug]} {トラップmystuff SIGINT}

あるいは、他の信号を使用してデバッガにトラップすることもできます。

トラップはSIGALRMの動作をオーバーライドさせません.SIGALRMの動作はExpectに内部的に使用されるためです。 disconnectコマンドは、SIGALRMをSIG_IGN(無視)に設定します。 後続のspawnコマンド中に無効にする限り、これを再び有効にすることができます。

詳細はsignal(3)を参照してください。

待つ[args]
生成されたプロセス (または指定されていない場合は現在のプロセス )が終了するまで遅延します。

通常、 waitは4つの整数のリストを返します。 最初の整数は、待っていたプロセスのPIDです。 2番目の整数は、対応するスポーンIDです。 3番目の整数は、オペレーティングシステムのエラーが発生した場合は-1、そうでない場合は0です。 3番目の整数が0の場合、4番目の整数は生成されたプロセスによって返されるステータスです。 3番目の整数が-1の場合、4番目の整数はオペレーティングシステムによって設定されたerrnoの値です。 グローバル変数errorCodeも設定されます。

waitからの戻り値の最後に追加要素が現れることがあります。 オプションの第5要素は情報のクラスを識別する。 現在のところ、この要素の唯一の可能な値はCHILDKILLEDです。この場合、次の2つの値はCスタイルの信号名と短いテキスト記述です。

-iフラグは、指定されたspawn_id( プロセス IDではない)に対応するプロセスを待機することを宣言します 。 SIGCHLDハンドラの内部では、spawn id -1を使用して、生成されたプロセスを待つことができます。

-nowaitフラグを指定すると、待機が成功したことの通知とともに待機が即時に戻ります。 プロセスが終了すると(後で)明示的に待たずに自動的に消えます。

waitコマンドは、引数 "-i -1"を使用してforkしたプロセスを待つためにも使用できます。 生成されたプロセスでの使用とは異なり、このコマンドはいつでも実行できます。 どのプロセスが収穫されるかは制御できません。 ただし、戻り値はプロセス IDを調べることができます。

ライブラリ

ExpectはExpectスクリプト用の2つのビルトインライブラリを自動的に知っています。 これらは、変数exp_libraryとexp_exec_libraryに指定されたディレクトリによって定義されます。 両方とも、他のスクリプトで使用できるユーティリティファイルを格納しています。

exp_libraryにはアーキテクチャに依存しないファイルが含まれています。 exp_exec_libraryにはアーキテクチャ依存のファイルが含まれています。 システムによっては、両方のディレクトリが完全に空である可能性があります。 ファイル$ exp_exec_library / cat-buffersの存在は、/ bin / catがデフォルトでバッファリングするかどうかを示します。

PRETTY-PRINTING

vgrindの定義は、pretty-printのExpectスクリプトで利用できます。 Expectディストリビューションで提供されているvgrind定義が正しくインストールされていると仮定すると、次のように使用できます。

vgrind -lexpectファイル

使用例

マニュアルページで説明されているように、すべてをまとめておく方法は多くありません。 Expectディストリビューションのサンプルディレクトリにあるサンプルを読んで試してみることをお勧めします。 それらの一部は実際のプログラムです。 他は単に特定のテクニックを説明するものであり、もちろんカップルは簡単なハックです。 INSTALLファイルには、これらのプログラムの概要があります。

Expect論文(see節も参照)も有用です。 いくつかの論文では、以前のバージョンのExpectに対応する構文を使用していますが、それに付随する根拠はまだ有効であり、このマニュアルページよりもはるかに詳しく説明されています。

警告

拡張機能はExpectのコマンド名と衝突する可能性があります。 例えば、 sendはTkによってまったく異なる目的のために定義されています。 このため、 Expectコマンドのほとんどは "exp_XXXX"としても利用できます。 "exp"、 "inter"、 "spawn"、 "timeout"で始まるコマンドと変数にはエイリアスはありません。 環境間でこの互換性が必要な場合は、拡張コマンド名を使用してください。

期待は、スコープのかなり自由な見方を取る。 特に、 Expectプログラム固有のコマンドで読み取られた変数は、まずローカルスコープから検索され、見つからなければグローバルスコープから検索されます。 例えば、これは、あなたが書き込むすべての手続きに "グローバルタイムアウト"を置く必要性を避けます。 一方、書かれた変数は常に(グローバルコマンドが発行されていない限り)ローカルスコープにあります。 これが引き起こす最も一般的な問題は、プロシージャ内でspawnが実行されるときです。 プロシージャの外部では、 spawn_idは存在しなくなり、生成されたプロセスは単にスコープのためにアクセスできなくなります。 そのようなプロシージャに「グローバルspawn_id」を追加します。

マルチスパム機​​能を有効にできない場合(つまり、システムがselect(BSD *。*)、poll(SVR> 2)などもサポートしていない場合)、 Expectは一度に1つのプロセスしか制御できません。 この場合、 spawn_idを設定しないでください。また、生成されたプロセスが実行されている間にexecによってプロセスを実行しないでください。 さらに、複数のプロセス(ユーザーを含む)から同時に期待することはできません。

ターミナルパラメータはスクリプトに大きな影響を与えます。 たとえば、エコーを探すためにスクリプトが書き込まれている場合、エコーをオフにすると誤動作します。 このため、Expectはデフォルトでsaneのターミナルパラメータを強制します。 残念ながら、これは他のプログラムにとって不愉快なものにする可能性があります。 例として、emacsシェルは "通常の"マッピングを変更したい:改行はキャリッジリターン改行の代わりに改行にマップされ、エコーは無効になる。 これにより、入力行を編集するためにemacsを使うことができます。 残念ながら、期待はおそらくこれを推測することはできません。

Expectが端末パラメータのデフォルト設定を上書きしないように要求できますが、そのような環境用のスクリプトを書くときは非常に注意する必要があります。 emacsの場合は、エコーや行末のマッピングなどには依存しないでください。

受け入れられた引数が1つのリストにブレースされたコマンド( 期待バリアントと相互作用 )は、リストが実際には1つの引数か複数のものかを決定するヒューリスティックを使用します。 ヒューリスティックは、リストが実際にそれらの間に空白以外の文字を含む複数の埋め込み\ nを持つ単一の引数を表す場合にのみ失敗する可能性があります。 これは十分に起こりそうにないようですが、引数 "-nobrace"を使用して、単一の引数を単一の引数として扱うことができます。 これは、機械で生成されたExpectコードとともに使用される可能性があります。 同様に、-braceは、単一の引数を複数のパターン/アクションとしてhandleにします。

バグ

プログラムを「性別」(「Smart EXEC」または「Send-Expect」のいずれか)と命名するのは本当に魅力的でしたが、良い意味合い(またはおそらく純粋主義)が勝っていました。

いくつかのシステムでは、シェルが生成されたとき、それはttyにアクセスできないと文句を言いますが、とにかく動いています。 つまり、あなたのシステムには、 Expectが知らない制御用のttyを得るための仕組みがあります。 それが何であるかを見つけて、この情報を私に送り返してください。

Ultrix 4.1(少なくともこのバージョンの最新バージョン)では、1000000を超えるタイムアウトは0に等しいと見なされます。

SIGCHLDハンドラを定義した場合、Digital UNIX 4.0A(およびその他のバージョン)はptysの割り当てを拒否します。 詳細については、grantptのページを参照してください。

IRIX 6.0はptyパーミッションを正しく処理しないため、Expectが以前に他の人が使用していたptyを割り当てようとすると失敗します。 IRIX 6.1にアップグレードしてください。

TERMが設定されていない場合、Telnet(SunOS 4.1.2でのみ検証済み)がハングします。 これは、TERMを定義していないcronスクリプト、およびcgiスクリプトでの問題です。 したがって、通常は関係のないタイプに明示的に設定する必要があります。 それはちょうど何かに設定する必要があります! 次のように、ほとんどの場合十分です。

set env(TERM)vt100

SHELLとHOMEが設定されていない場合、ヒント(BSDI BSD / OS 3.1 i386でのみ検証済み)がハングします。 これは、これらの環境変数を定義していない cron 、atおよびcgiスクリプトでの問題です。 したがって、通常は関係のないタイプに明示的に設定する必要があります。 それはちょうど何かに設定する必要があります! 次のように、ほとんどの場合十分です。

set env(SHELL)/ bin / sh set env(HOME)/ usr / local / bin

プロセスがファイル記述子を閉じた後、カーネルが未読の出力を10〜15秒後にスローするように設計されています(実際の数は実装依存です)。 したがって、

スポーン日付スリープ20期待

失敗するでしょう。 これを避けるには、非対話型プログラムを起動するのではなくexecで起動します 。 このような状況は考えられるが、実際には、本当にインタラクティブなプログラムの最終的な出力がこの動作のために失われる状況には、まったく遭遇していない。

一方、Cray UNICOS ptysは、 プロセスがファイル記述子を閉じた直後に未読の出力をすべて破棄します。 私はこれをCrayに報告し、彼らは解決に取り組んでいます。

ttyインターフェイスがUART設定を変更している場合や、スタート/ストップビットを探してボーレートを一致させる場合など、プロンプトと応答の間に遅延が必要な場合があります。 通常、これはすべて2〜2寝るだけです。 より堅牢な手法は、ハードウェアが入力を受け取る準備ができるまで再試行することです。 次の例では、両方の戦略を使用しています。

送信 "速度9600 \ r"; スリープ1 expect {timeout {"\ r"; exp_continue} $プロンプト}

trap-codeは、スリープのようなTclのイベントループにあるコマンドでは動作しません。 問題は、イベントループで、Tclが非同期イベントハンドラからの戻りコードを破棄することです。 回避策は、トラップコードにフラグを設定することです。 次に、コマンドの直後のフラグ(つまりスリープ)を確認します。

expect_backgroundコマンドは、-timeout引数を無視し、一般的なタイムアウトの概念を持ちません。

"予想ヒント"

Expectについては直感的ではないことがいくつかあります。 このセクションでは、これらのことのいくつかをいくつか提案してみます。

シェルプロンプトを認識する方法は、一般的な予想上の問題です。 これらは異なる人や異なるシェルによってカスタマイズされているので、プロンプトを知らなくても移植可能なrloginを難しくすることができます。 環境変数EXPECT_PROMPTにプロンプ​​ト(特にその終わり)を記述した正規表現をユーザに格納させるのが合理的な慣習です。 次のようなコードを使用できます。 EXPECT_PROMPTが存在しない場合、コードはまだ正常に機能する可能性が高いです。

プロンプト "(%|#| \\ $)$"を設定する#デフォルトプロンプトキャッチ{プロンプト$ env(EXPECT_PROMPT)

私はあなたが見たいと思うものの終わりを含む期待パターンを書くことをお勧めします。 これは、全体を見る前に質問に答える可能性を避けます。 また、あなたが完全に見る前に質問に答えることができるかもしれませんが、あなたが早く答えると、質問の途中で答えが返ってくることがあります。 言い換えれば、結果として得られる対話は正しいが、スクランブルされて見える。

ほとんどのプロンプトには最後にスペース文字が含まれています。 たとえば、ftpからのプロンプトは 'f'、 't'、 'p'、 '>'および。 このプロンプトと一致させるには、これらの各文字を考慮する必要があります。 空白を入れないのはよくある間違いです。 空白を明示的に入れます。

X *形式のパターンを使用すると、*はXの最後から受信した最後のものまでのすべての出力と一致します。 直感的に聞こえるかもしれませんが、 "最後に受け取った"というフレーズは、コンピュータの速度やカーネルとデバイスドライバの両方によるI / Oの処理によって変わる可能性があるため、やや混乱します。

特に、人間は、実際にはほとんどのプログラムが一度に1行ずつ出力を生成すると、プログラム出力が巨大なチャンク(原子的に)に達するのが見られる傾向があります。 これが当てはまる場合、前の段落のパターンの*は、一致した時点で受信したすべての出力であったため、より多くのように見えますが、現在の行の末尾にのみ一致する可能性があります。

あなたのパターンが特にそれを説明しない限り、さらなる出力が来ていることを知る方法はありません。

ライン指向のバッファリングによっても賢明ではありません。 プログラムではバッファリングの種類について約束することはめったにないだけでなく、システムの消化不良によって出力行が途切れてしまい、ランダムな場所で行が途切れることがあります。 したがって、パターンを書くときにプロンプ​​トの最後の数文字を表現できる場合は、そうすることが賢明です。

プログラムの最後の出力でパターンを待っていて、プログラムが何か別のものを出力した場合は、 timeoutキーワードでそれを検出することができません。 その理由は、 expectがタイムアウトにならず、代わりにeof指示を得るということです。 その代わりに使用してください。 両方とも使用してください。 そうすれば、その行が移動した場合でも、行自体を編集する必要はありません。

改行は通常、ターミナルドライバによって出力されたときに改行、改行シーケンスに変換されます。 したがって、例えばprintf( "foo \ nbar")のように、2つの行を明示的に一致させるパターンが必要な場合は、パターン "foo \ r \ nbar"を使用する必要があります。

同様の変換は、 expect_userを介してユーザーから読み取るときにも発生します。 この場合、returnキーを押すと改行に変換されます。 Expectがその端末をrawモード(telnetなど)に設定しているプログラムに渡すと、プログラムは真の復帰を期待しているので、問題が起こります。 (一部のプログラムでは、改行を自動的に改行に変換するという点で実際には寛容ですが、ほとんどの場合、そうではありません)。残念ながら、プログラムが端末をrawモードにしていることを知る方法はありません。

手作業で改行をリターンに置き換えるのではなく、 "stty raw"コマンドを使用して翻訳を停止するという方法があります。 ただし、これは、調理済みの行編集機能を使用できなくなることを意味します。

対話は暗黙のうちに端末をrawモードに設定するので、この問題は発生しません。

パスワード(または他の個人情報)をExpectスクリプトに格納すると便利なことがよくあります。 これは、コンピュータに保存されているものは誰でもアクセスできるため、これはお勧めできません。 したがって、対話形式でスクリプトからパスワードを入力することは、それらを文字通り埋め込むよりもスマートな考えです。 それにもかかわらず、時にはそのような埋め込みが唯一の可能性である。

残念ながら、UNIXファイルシステムには、実行可能だが読めないスクリプトを直接作成する方法はありません。 setgidシェルスクリプトをサポートするシステムは、以下のようにこれを間接的にシミュレートすることができます:

通常通り、 Expectスクリプト(秘密データを含む)を作成します。 権限を750(-rwxr-x ---)にして、信頼できるグループ、つまりそれを読み取ることが許可されているグループが所有するようにします。 必要に応じて、この目的のために新しいグループを作成します。 次に、以前と同じグループが所有する権限2751(-rwxr-s-x)を持つ/ bin / shスクリプトを作成します。

結果は誰でも実行できる(読み込まれる)スクリプトです。 呼び出されると、 Expectスクリプトが実行されます。

"参照してください"

Tcl (3)、 libexpect (3)
Don Libes、pp。602、ISBN 1-56592-090-2、O'Reilly and Associates、1995年、 「インタラクティブ・プログラムを自動化するためのTclベースのツールキット」を参照してください。
1990年6月11-15日、カリフォルニア州アナハイムのUSENIX Conference 1990年夏の予稿集、 Don Libesの「インタラクティブ性の制御不能な適合を治すことを期待する
.I 1990年10月17-19日、コロラド州コロラドスプリングズの1990年USENIX大規模インストールシステム管理会議の講演資料、Don Libesの「システム管理タスクを自動化するための期待を使用する
1990年1月22-26日ワシントンDCのUSENIX Conference 1990年冬季大会の議事録John Ousterhout著「Tcl:組み込み可能なコマンド言語」I「期待する:対話型プログラムを制御するスクリプト」Don Libes、Computing Systems 、Vol。 米国カリフォルニア州サンアントニオの4月2日、カリフォルニア大学プレスジャーナル、1991年11月.I "回帰テストと適合性テスト対話型プログラム"、ドンリベス、1992年夏の予稿集USENIXカンファレンス、135-144ページ、 1992年6月12日〜15日、I。インディアナ州ウエストサセックスのJohn Wiley&Sons、ソフトウェア - 実践&経験、Don Libes著、 "Kibitz - 複数のインタラクティブプログラムを結びつける"

1993年6月10-11日、カリフォルニア州バークレー、1993年Tcl / Tkワークショップの講演資料、Don Libes著、「Tclアプリケーションのためのデバッガ」、第23巻、第5号、1993年5月。

著者

国立標準技術研究所のドン・リベス

謝辞

TclのJohn OusterhoutとインスピレーションのScott Paisleyに感謝します。 Expectの自動設定コードのRob Savoyeに感謝します。

HISTORYファイルには、 期待の進化の多くが記録されています。 それは興味深い読書をし、あなたにこのソフトウェアへのさらなる洞察を与えるかもしれません。 私にバグ修正を送ってくれた人に感謝し、他の支援をしました。

Expectの設計と実装は、米国政府によって部分的に支払われたため、公開されています。 しかし、著者とNISTは、このプログラムとドキュメンテーションまたはその一部が使用されている場合には、クレジットを希望します。