このセクションでは非同期プロセス(asynchronous process)を作成する方法について説明します。非同期プロセスは作成後にEmacsと並列して実行され、Emacsは以降のセクション(プロセスへの入力の送信とプロセスからの出力の受信を参照)で説明する関数を使用してプロセスとコミュニケーションができます。プロセスコミュニケーションは部分的に非同期なだけであることに注意してください。Emacsはこれらの関数を呼び出したときだけプロセスとのデータを送受信できます。
非同期プロセスはpty(pseudo-terminal:
疑似端末)、またはpipeのいずれかを通じて制御されます。ptyかpipeの選択はデフォルトでは変数process-connection-type
(以下参照)の値にもとづいてプロセス作成時に行われます。Shellモードのように利用可能ならユーザーから可視なプロセスには、プロセスと子プロセス間でジョブ制御(C-c、C-z等)が可能であり、インタラクティブなプログラムではptyを端末デバイスとして扱いますがpipeはそのような機能をサポートしないのでptyが通常は好まれます。しかし内部的な目的のためにLispプログラムが使用する(サブプロセスとユーザーの相互作用が要求されない)サブプロセスでは、サブプロセスとLispプログラム間で大量データのやり取りが要求される場合には、pipeがより効率的なのでpipeの使用が最良な場合がままあります。さらに多くのシステムではptyの合計数に制限があり、それを浪費するのは得策ではありません。
この関数は非同期サブプロセスを開始するための基本的な低レベルなプリミティブである。これはサブプロセスを表すプロセスオブジェクトをリターンする。以下で説明するより高レベルなstart-processと比較すると、この関数はキーワード引数を受け取り、より柔軟であり、単独の呼び出しでプロセスフィルターやセンチネルを指定できる。
引数argsはkeyword/argumentペアのリスト。キーワードの省略は値nilでそれを指定することと常に等価。以下は意味のあるキーワード:
:name nameプロセス名として文字列nameを使用する。その名前のプロセスがすでに存在すれば、(‘<1>’、...の追加により)一意となるようにnameを修正する。
:buffer bufferプロセスバッファーとしてbufferを使用する。値がnilなら、そのサブプロセスには何のバッファーも関連付けられない。
:command commandプロセスのコマドラインとしてcommandを使用する。値はプログラムの実行可能ファイル名で始まり、後にプログラムの引数として与える文字列が続くリストであること。リストの最初の要素がnilなら、Emacsは新たな擬似端末(pty)を作成して、実際には何もプログラムを実行せずに入出力をbufferに関連付ける。この場合には残りのリスト要素は無視される。
:coding codingcodingがシンボルなら、それはその接続にたいする読み取りと書き込みの両方で使用するコーディングシステムを指定する。codingがコンスセル(decoding . encoding)なら読み取りにdecoding、書き込みにencodingが使用される。プログラムに書き込むデータのエンコーディングに使用されるコーディングシステムは、コマンドライン引数のエンコーディングにも使用される(しかしプログラム自身にたいしてファイル名を別のファイル名にエンコードすることはない。file-name-coding-systemを参照)。
codingがnilなら、デフォルトのコーディングシステム検出ルールを適用する。デフォルトのコーディングシステムを参照のこと。
:connection-type typeサブプロセスとの対話に使用するデバイスタイプを初期化する。値にはptyを使用するpty、pipeを使用するpipe、または変数process-connection-typeの値から継承されるデフォルトを使用するnilを指定できる。typeがコンスセル(input . output)の場合には、標準入力にinput、標準出力(および:stderrがnilなら標準エラーも)にoutputが使用される。
ptyが利用できないシステム(MS-Windows)ではこのパラメーターを無視して、無条件でpipeが使用される。
:noquery query-flagプロセスqueryフラグをquery-flagに初期化する。exit前の問い合わせを参照のこと。
:stop stoppedstoppedが与えられた場合にはnilでなければならない。非nil値の使用はすべてエラーとなる。それ以外の場合には:stopは無視される。これはpipeプロセスのような他のプロセスタイプへの互換性のために維持されている。非同期サブプロセスがstopped状態で開始されることはあり得ない。
:filter filterプロセスフィルターをfilterに初期化する。未指定ならデフォルトフィルターが提供されるが、これは後からオーバーライドできる。プロセスのフィルター関数を参照のこと。
:sentinel sentinelプロセスセンチネルをsentinelに初期化する。未指定ならデフォルトセンチネルが使用されるが、これは後からオーバーライドできる。センチネル: プロセス状態の変更の検知を参照のこと。
:stderr stderrプロセスの標準エラーにstderrを割り当てる。値が非nilならバッファー、または以下で説明するmake-pipe-processで作成されたpipeのいずれかであること。stderrがnilなら標準エラーを標準出力と合成して、両者をbufferかfilterに送信する。
stderrがバッファーならEmacsはpipeプロセス、標準エラープロセス(standard error
process)を作成する。このプロセスはデフォルトフィルター(プロセスのフィルター関数を参照)、センチネル(センチネル: プロセス状態の変更の検知を参照)、コーディングシステム(デフォルトのコーディングシステムを参照)をもつ。その一方で、自身のquery-on-exitフラグとしてquery-flagを使用する(exit前の問い合わせを参照)。このプロセスはstderrバッファーに関連づけられて、そこに出力(メインプロセスの標準エラー)を送信する(プロセスのバッファーを参照)。標準エラープロセスにたいするプロセスオブジェクトを取得するには、get-buffer-processにstderrバッファーを渡せばよい。
stderrがpipeプロセスなら、Emacsはそれを新たなプロセス用の標準エラープロセスとして使用する。
:file-handler file-handlerfile-handlerが非nilなら、カレントバッファーのdefault-directoryにたいするファイル名ハンドラーを探して、プロセスを作成するためにそのファイル名ハンドラーを呼び出す。そのようなハンドラーがなければ、file-handlerがnilであるかのように処理する。
実際の接続情報で修正されたオリジナルの引数リストはprocess-contactを通じて利用できる。
サブプロセスのカレント作業ディレクトリー(CWD: current working
directory)はカレントバッファーのdefault-directoryがローカル(unhandled-file-name-directoryにより判断される)ならその値、それ以外は~。リモートディレクトリーでプロセスを実行したければ、make-processに:file-handler
tを渡せばよい。この場合には、カレントのワーキングディレクトリー(CWD)はdefault-directoryの(file-local-nameで決定される)ローカル部分となる。
ファイル名ハンドラーの実装に依存して、結果となるプロセスオブジェクトへのfilterやsentinelの適用が不可能かもしれない。:stderr引数はpipeプロセスではあり得ないので、ファイル名ハンドラーはこれにたいしてpipeプロセスをサポートしない。:stderr引数としてバッファーは許されており、バッファーのコンテンツはpipeプロセスを使用することなく表示される。プロセスのフィルター関数およびプロセスの出力を受け取るを参照のこと。
いくつかのファイルハンドラーはmake-processをサポートしないかもしれない。そのような場合には、この関数は何も行わずにnilをリターンする。
この関数は子プロセスにアタッチ可能な双方向のpipeを作成する。これはmake-processの:stderrキーワードと併用することで有用。この関数はプロセスオブジェクトをリターンする。
引数argsはkeyword/argumentペアのリスト。キーワードの省略はそのキーワードに値nilを指定することと常に等価。
以下は意味のあるキーワード。
:name nameプロセス名として文字列nameを使用する。make-processの場合のように、一意にするために必要に応じて変更され得る。
:buffer bufferプロセスバッファーとしてbufferを使用する。
:coding codingcodingがシンボルなら、それはその接続にたいする読み取りと書き込みの両方で使用するコーディングシステムを指定する。codingがコンスセル(decoding . encoding)なら読み取りにdecoding、書き込みにencodingが使用される。
codingがnilなら、デフォルトのコーディングシステム検出ルールを適用する。デフォルトのコーディングシステムを参照のこと。
:noquery query-flagプロセスqueryフラグをquery-flagに初期化する。exit前の問い合わせを参照のこと。
:stop stoppedstoppedが非nilなら停止状態でプロセスを開始する。停止状態ではpipeプロセスは入力データを受け取らないが出力データは送信できる。停止状態はstop-processでセットしてcontinue-processでクリアーされる(プロセスへのシグナルの送信を参照)。
:filter filterプロセスフィルターをfilterに初期化する。未指定ならデフォルトフィルターが提供されるが後で変更できる。プロセスのフィルター関数を参照のこと。
:sentinel sentinelプロセスセンチネルをsentinelに初期化する。未指定ならデフォルトセンチネルが使用されるが後で変更できる。センチネル: プロセス状態の変更の検知を参照のこと。
実際の接続情報で修正されたオリジナルの引数リストはprocess-contactを通じて利用できる。
この関数はcall-processの類似したインターフェースを提供する、make-process周辺の高レベルのラッパー。これは新たに非同期サブプロセスを作成して、指定されたprogramの実行をその内部で開始する。これはLispで新たなサブプロセスを意味するプロセスオブジェクトをリターンする。引数nameはプロセスオブジェクトの名前を指定する。make-processの場合のように、一意な名前となるように必要に応じて修正する。バッファーbuffer-or-nameはそのプロセスに関連付けるバッファー。
programがnilならEmacsは疑似端末(pty)を新たにオープンして、サブプロセスを新たに作成することなくptyの入力と出力をbuffer-or-nameに関連付ける。この場合には残りの引数argsは無視される。
残りのargsはサブプロセスにコマンドライン引数を指定する文字列。
以下の例では1つ目のプロセスを開始して100秒間実行(というよりはsleep)される。その間に2つ目のプロセスを開始して、一意性を保つために‘my-process<1>’という名前が与えられる。これは1つ目のプロセスが終了する前にバッファー‘foo’の最後にディレクトリーのリストを挿入する。その後に2つ目のプロセスは終了して、その旨のメッセージがバッファーに挿入される。さらに遅れて1つ目のプロセスが終了して、バッファーに別のメッセージが挿入される。
(start-process "my-process" "foo" "sleep" "100")
⇒ #<process my-process>
(start-process "my-process" "foo" "ls" "-l" "/bin")
⇒ #<process my-process<1>>
---------- Buffer: foo ----------
total 8336
-rwxr-xr-x 1 root root 971384 Mar 30 10:14 bash
-rwxr-xr-x 1 root root 146920 Jul 5 2011 bsd-csh
...
-rwxr-xr-x 1 root root 696880 Feb 28 15:55 zsh4
Process my-process<1> finished
Process my-process finished
---------- Buffer: foo ----------
start-processと同じようにこの関数は非同期サブプロセスを開始して、その内部でprogramを実行してそのプロセスオブジェクトをリターンする。
start-processとの違いは、この関数がdefault-directoryの値にもとづいてファイル名ハンドラーを呼び出すかもしれないという点である。このハンドラーはローカルホスト上、あるいはdefault-directoryに応じたリモートホスト上でprogramを実行すること。後者の場合には、default-directoryのローカル部分はそのプロセスのワーキングディレクトリーになる。
この関数はprogramやargsの残りにたいしてファイル名ハンドラーの呼び出しを試みない。programはargsのいずれかがリモートファイル構文(特定のファイル名の“Magic”の作成を参照)を使用する場合には、file-local-nameを通じて実行することにより、それらの名前をdefault-directoryに相対的な名前やリモートホスト上でローカルにファイルを識別する名前に変換しなければならないことが理由。
そのファイル名ハンドラーの実装によっては、リターン結果のプロセスオブジェクトにprocess-filterやprocess-sentinelを適用することができないかもしれない。プロセスのフィルター関数とセンチネル: プロセス状態の変更の検知を参照のこと。
いくつかのファイル名ハンドラーはstart-file-processをサポートしないかもしれない(たとえばange-ftp-hook-function関数)。そのような場合には、この関数は何も行わずにnilをリターンする。
この関数はstart-processと同様だが、指定されたcommandの実行にshellを使用する点が異なる。引数commandはshellコマンド文字列。変数shell-file-nameはどのshellを使用するかを指定する。
make-processやstart-processでプログラムを実行せずにshellを通じて実行することの要点は、引数内のワイルドカード展開のようなshell機能を利用可能にするためである。そのためにはコマンド内に任意のユーザー指定引数を含めるなら、任意の特別なshell文字がshellでの特別な意味をもたないように、まずshell-quote-argumentでそれらをクォートするべきである。shell引数を参照のこと。ユーザー入力にもとづいたコマンド実行時には当然セキュリティ上の影響も考慮するべきである。
この関数はstart-process-shell-commandと似ているが、内部的にstart-file-processを使用する点が異なる。これによりdefault-directoryに応じてリモートホスト上でもcommandを実行できる。
この変数は非同期サブプロセスと対話するために使用するデバイスタイプを制御する。これが非nilの場合には利用可能ならpty、それ以外ならpipeが使用される。
process-connection-typeの値はmake-processやstart-processの呼び出し時に効果を発揮する。そのためにこれらの関数の呼び出し前後でこの変数をバインドすることにより、サブプロセスとやり取りする方法を指定できる。
この変数の値は非nil値の:stderrパラメーターでmake-processが呼び出された際には無視される。この場合にはEmacsはpipeを使用してプロセスと対話する。ptyが利用不能(MS-Windows)な場合にも無視される。
(let ((process-connection-type nil)) ; pipeを使用
(start-process ...))
与えられたサブプロセスが実際にはpipeとptyのどちらを取得したかを判断するには関数process-tty-nameを使用する(プロセスの情報を参照)。
もしプロセスのセンチネルやフィルターの関数にエラーがあると、Emacsはそのエラーを表示した後に、ユーザーが問題となっているエラーを確認できるように(デフォルトでは)process-error-pause-timeに設定された秒数の間一時停止する。ただしEmacsが応答しなくなる状況に導かれる可能性もある(あまりに大量のエラーが発生した場合など)ので、process-error-pause-timeを0にセットして無効にできる。