trap ‘処理’ EXIT

以下の形式でtrapコマンドを使用して、スクリプトの終了時に必ず実行される処理を設定できる。

trap '処理' EXIT

例えば、スクリプトの終了時にログを出力する場合は以下のように実行する。

trap 'echo "スクリプトが終了しました"' EXIT
# スクリプトの処理
echo "スクリプトの処理が完了しました"

実行すると、スクリプトの終了時に必ずスクリプトが終了しましたと表示される。

$ sh script.sh
スクリプトの処理が完了しました
スクリプトが終了しました

関数を定義して実行する

処理が長くなる場合は関数として定義すれば見通しが良くなる。

trap cleanup EXIT
function cleanup() {
    echo "スクリプトが終了しました"
}

echo "スクリプトの処理が完了しました"

実行すると、スクリプトの終了時に必ずスクリプトが終了しましたと表示される。

$ sh script.sh
スクリプトの処理が完了しました
スクリプトが終了しました

エラーで途中終了した場合も実行される

trapコマンドは、スクリプトがエラーで途中終了した場合でも実行される。

set -e
trap 'echo "スクリプトが終了しました"' EXIT

ls missing_file.txt  # エラーを発生させる
echo "このメッセージは表示されません"

実行するとmissing_file.txtは存在しないためエラーが発生。
スクリプトは途中で終了するものの、スクリプトが終了しましたは表示される。

$ sh script.sh
ls: cannot access 'missing_file.txt': No such file or directory
スクリプトが終了しました

trapが実行されない場合

trapコマンドは強制的にプロセスを終了させる場合には実行されない。

trap 'echo "スクリプトが終了しました"' EXIT

sleep 60 &
PID=$!
echo "PID: $PID"
wait

以下のような場合、trapによる処理は実行されない:

  • kill -9で強制終了した場合
  • システムクラッシュやハードウェア障害
  • 電源切断など物理的な終了

その他のシグナル

trapコマンドはEXIT以外にも様々なシグナルを捕捉できる。

trap 'echo "Ctrl+Cで中断されました"' INT
trap 'echo "終了シグナルを受信しました"' TERM
trap 'echo "スクリプトが終了しました"' EXIT

sleep 60

それぞれのシグナルは以下のような状況で発生する。

  • INT: Ctrl+Cを押したとき、割り込みシグナルが送信されたとき
  • TERM: killコマンドで終了シグナルが送信されたとき、システムシャットダウンとき
  • EXIT: スクリプトが終了するとき