= Trap 組込みコマンド
:encoding: UTF-8
:lang: ja
//:title: Yash マニュアル - Trap 組込みコマンド

dfn:[Trap 組込みコマンド]はシェルがシグナルを受信したときの動作を設定します。

[[syntax]]
== 構文

- +trap+
- +trap {{動作}} {{シグナル}}...+
- +trap {{シグナル番号}} [{{シグナル}}...]+
- +trap -p [{{シグナル}}...]+

[[description]]
== 説明

Trap コマンドはシェルプロセスがシグナルを受信したときの動作 (dfn:[トラップ]) を表示または設定します。

オペランドに{{動作}}と{{シグナル}}を指定して trap コマンドを実行すると、シェルが{{シグナル}}を受信した際に指定した{{動作}}を行うようになります。最初のオペランドが{{シグナル番号}}の場合、それと残りの{{シグナル}}に対する動作は、動作として +-+ が指定されたときと同様に標準の動作に設定されます。

+-p+ (+--print+) オプションを指定した場合またはオペランドを一つも指定していない場合は、trap コマンドは現在のトラップの設定状況をコマンドとして解釈可能な形式で標準出力に出力します。{{シグナル}}が与えられているときはそのシグナルに関する設定を、与えられていないときは全ての設定を出力します。ただし、特定の状況では trap コマンドは現在の設定ではなく以前の設定を表示します (下記補足参照)。

[[options]]
== オプション

+-p+::
+--print+::
現在のトラップの設定を表示します。

[[operands]]
== オペランド

{{動作}}::
シグナルを受信した際の動作を指定します。{{動作}}がハイフン一つ (+-+) ならば、シェルはシステムで規定された標準の動作を行います。{{動作}}が空文字列ならば、シェルはシグナルを無視します。それ以外の値を指定すると、シェルはこのオペランドをコマンドとみなして、シグナル受信時にこれを解釈・実行します (コマンドの実行中にシグナルを受信したときは、コマンドが終了した後にトラップを実行します)。

{{シグナル}}::
動作の対象となるシグナルです。シグナルはシグナル番号とシグナル名のどちらかで指定します。
+
{{シグナル}}として +0+ または +EXIT+ を指定すると、これはシェルの終了時に発生する仮想のシグナルを指定しているとみなします。この仮想のシグナルに対して設定された{{動作}}は、シェルが正常終了する直前に実行されます。

{{シグナル番号}}::
{{シグナル}}と同様ですが、シグナルを番号で指定します。

[[exitstatus]]
== 終了ステータス

トラップが正しく設定または表示されたときは終了ステータスは 0 です。エラーがあると終了ステータスは非 0 です。

[[notes]]
== 補足

Trap コマンドは{zwsp}link:builtin.html#types[特殊組込みコマンド]です。

POSIX には +-p+ (+--print+) オプションに関する規定はありません。よってこのオプションは link:posix.html[POSIX 準拠モード]では使えません。

POSIX は、シグナル名は +INT+ や +QUIT+ のように最初の SIG を除いた形で指定しなければならないと規定しています。Yash では、拡張として SIG を付けた形でも指定できますし、シグナル名の大文字と小文字を区別しません (このような拡張は POSIX でも認められています)。

=== 出力の再利用

Trap コマンドが出力したトラップの設定を変数に保存しておき、後で link:_eval.html[eval コマンド]でそれを実行することで元のトラップの設定を復活させることができます。

----
saved_trap=$(trap)
trap '...' INT
eval "$saved_trap"
----

ただし、このテクニックの挙動には裏があります。Trap コマンドの出力を変数に保存するために{zwsp}link:expand.html#cmdsub[コマンド置換]を使用しますが、コマンド置換は{zwsp}link:exec.html#subshell[サブシェル]で実行されます。サブシェルの開始時にトラップの設定は解除されるため、本来ならばサブシェル内の trap コマンドは何も出力せず、結果として変数にはトラップが保存されないことになります。

この問題を回避するため、POSIX は以下のうちどちらかの挙動を執ることをシェルに求めています。

- コマンド置換の中身がただ一つの trap コマンドである場合は、そのコマンド置換を実行するサブシェルの開始時にトラップ設定を解除しない。
- サブシェルの開始時にトラップ設定を解除する際に、以前の設定を憶えておく。サブシェル内で trap コマンドがトラップ設定を出力する際、まだそのサブシェル内で別の trap コマンドがトラップ設定を変更していなければ、憶えておいた以前の設定を出力する。

Yash は二つ目の選択肢に従います。

// vim: set filetype=asciidoc expandtab:
