本文へスキップ
BecomeCoder

シェルスクリプトコース · 第7章 安全に書く · レッスン32

trap ― 後片付けを必ず実行する

ブラウザで完結

導入

一時ファイルを作って処理し、最後に消す。ところが途中でエラーになって、一時ファイルが残り続ける——ディスクを圧迫する原因の定番です。trap を使えば、どう終わっても後片付けが実行されます。

説明

trap 'コマンド' EXIT は、「スクリプトが終わるとき、必ずこのコマンドを実行する」という予約です。

#!/bin/bash
set -e

TMP_FILE=/tmp/work.txt

# どんな終わり方でも一時ファイルを消す
trap 'rm -f "$TMP_FILE"; echo "後片付けをしました"' EXIT

echo "一時ファイルを作ります"
echo "作業データ" > "$TMP_FILE"
cat "$TMP_FILE"

echo "処理が終わりました"
flowchart TD
    A["trap '後片付け' EXIT を登録"] --> B["本体の処理"]
    B --> C{"どう終わった?"}
    C -->|"正常終了"| D["後片付けが走る"]
    C -->|"エラーで exit"| D
    C -->|"Ctrl+C で中断"| D
    D --> E["一時ファイルは必ず消える"]

EXIT のほかにもシグナルを指定できます。

シグナルいつ発生するか
EXITどんな理由でもスクリプトが終わるとき
INTCtrl+C で中断されたとき
TERMkill で終了を要求されたとき

多くの場合 EXIT だけで足ります。「終わるときは必ず通る」からです。

trap登録した時点より後にしか効きません。だから一時ファイルを作るに登録するのが定石です。

mktemp コマンドを使うと、他と衝突しない一時ファイル名を作れます。TMP_FILE=$(mktemp)trap 'rm -f "$TMP_FILE"' EXIT はセットで覚えてください。

やってみよう

スクリプトを実行して、最後に 後片付けをしました が出ることを確かめましょう。次に cat "$TMP_FILE" の行を cat noexist.txt に変えて実行してください。set -e でエラー終了しますが、それでも後片付けは実行されることが分かります。

演習

trap に登録するメッセージを 一時ファイルを削除しました に変えて実行してください。

ヒント1を見る

trap '…; echo "…"' EXITecho の中身を書き換えます。

ヒント2を見る

trap 'rm -f "$TMP_FILE"; echo "一時ファイルを削除しました"' EXIT

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

シェルスクリプト(シミュレート)

スクリプトを書くエディタと、それを動かす仮想シェルを読み込みます(本物のbashではなく、動きを再現した学習用の環境です)。
スクロールして表示された時点でも自動で読み込まれます。