導入
一時ファイルを作って処理し、最後に消す。ところが途中でエラーになって、一時ファイルが残り続ける——ディスクを圧迫する原因の定番です。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 | どんな理由でもスクリプトが終わるとき |
INT | Ctrl+C で中断されたとき |
TERM | kill で終了を要求されたとき |
多くの場合 EXIT だけで足ります。「終わるときは必ず通る」からです。
trap は登録した時点より後にしか効きません。だから一時ファイルを作る前に登録するのが定石です。
mktempコマンドを使うと、他と衝突しない一時ファイル名を作れます。TMP_FILE=$(mktemp)とtrap 'rm -f "$TMP_FILE"' EXITはセットで覚えてください。
やってみよう
スクリプトを実行して、最後に 後片付けをしました が出ることを確かめましょう。次に cat "$TMP_FILE" の行を cat noexist.txt に変えて実行してください。set -e でエラー終了しますが、それでも後片付けは実行されることが分かります。
演習
trap に登録するメッセージを 一時ファイルを削除しました に変えて実行してください。
ヒント1を見る
trap '…; echo "…"' EXIT の echo の中身を書き換えます。
ヒント2を見る
trap 'rm -f "$TMP_FILE"; echo "一時ファイルを削除しました"' EXIT