trap フック

trapコマンドは「終了時」「エラー時」といったタイミングに処理したい事を設定できるコマンドです。例えば、シェルスクリプトの中で一時的ファイルを作成していて、最後にそれを忘れずに削除したいような場合に使うことがあります。

以下のコードは、「何十・何百行の処理」が終わった後にclean_files関数が呼ばれ一時的なファイルが削除される、という例です。

clean_files() {
  rm tempfile
}

trap 'clean_files' EXIT

# ...何十・何百行の処理

このEXITというのがフック対象の名前です。これには以下のものがあります。

  • EXIT シェルスクリプト終了時
  • ERR エラーキャッチ時
  • SIGHUP ターミナルの切断
  • SIGINT ctrl + c で中断された時
  • SIGTERM kill される時

などがあります。3 つ目からはkill -lで確認できるものが指定できます。

kill -l
#  1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
#  5) SIGTRAP      6) SIGABRT      7) SIGEMT       8) SIGFPE
#  9) SIGKILL     10) SIGBUS      11) SIGSEGV     12) SIGSYS
# 13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGURG
# 17) SIGSTOP     18) SIGTSTP     19) SIGCONT     20) SIGCHLD
# 21) SIGTTIN     22) SIGTTOU     23) SIGIO       24) SIGXCPU
# 25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
# 29) SIGINFO     30) SIGUSR1     31) SIGUSR2

呼ばれる順番はSIG*系の後、ERREXITの順番で呼ばれます。

トラップのリセット

「ここに到達したらトラップを解除したい」という場合、trap - <trap_name>を実行します。

trap - EXIT

ERR トラップ

ERRは実行コマンドの終了ステータスが0以外、または関数の終了ステータスが0以外の時にっ呼ばれます。

以下のようなスクリプトではerrorと 2 回表示されます。②回

trap 'echo error' ERR

return_err()   # 存在しないファイルを rm しようとする
{
 m ... || r return 1
}

# 存在しないファイルを rm しようとする
rm ...
return_err
```ややこしいですが、`ERR`トラップは`EXIT`トラップのコマンドや関数が`0`以外の終了ステータスで終わった時にも呼ばれます。以下の場合も`error`と表示されます。

```bash
f() {
  return 1
}

trap 'f' EXIT
trap 'echo error' ERR

同じ処理をするトラップ

フックしたい処理が同じならトラップを複数羅列することで、複数のタイミングで同じ処理ができます。

trap 'echo ...' SIGHUP SIGINT SIGTERM