# Trap 組込みコマンド

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

## 構文

- `trap`

- `trap 動作 シグナル…`

- `trap シグナル番号 [シグナル…]`

- `trap -p [シグナル…]`

## 説明

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

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

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

## オプション

`-p`
`--print`

  現在のトラップの設定を表示します。

## オペランド

動作

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

シグナル

  動作の対象となるシグナルです。シグナルはシグナル番号とシグナル名のどちらかで指定します。

  シグナルとして `0` または `EXIT` を指定すると、これはシェルの終了時に発生する仮想のシグナルを指定しているとみなします。この仮想のシグナルに対して設定された動作は、シェルが正常終了する直前に実行されます。

シグナル番号

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

## 終了ステータス

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

## 補足

Trap コマンドは​特殊組込みコマンドです。

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

### 出力の再利用

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

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

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

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

- コマンド置換の中身がただ一つの trap コマンドである場合は、そのコマンド置換を実行するサブシェルの開始時にトラップ設定を解除しない。

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

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