Categories: linux

Linuxのtrapコマンド完全ガイド:シグナルをキャッチしてスマートに処理を制御する方法

Linuxシェルスクリプトでプロセスの終了や中断に柔軟に対応したい場面は少なくありません。たとえば、ユーザーがCtrl+Cを押してスクリプトを終了させたときに一時ファイルを削除したい、プロセスが強制終了されたときにログを記録したいといったケースです。そんなときに役立つのが trap コマンドです。trapコマンドを使えば、特定のシグナル(終了、割り込みなど)をキャッチして、独自の処理を定義できます。この記事では、trapコマンドの基本的な使い方から、実践的なスクリプト例までを詳しく解説します。シェルスクリプトを安全かつ柔軟に運用するための知識として、ぜひこの機会にtrapの使い方をマスターしてみてください。


trapコマンドとは?

trapコマンドは、BashやshなどのUnix系シェルで使える組み込みコマンドの1つです。特定のシグナル(例:SIGINT, SIGTERM, EXITなど)を受け取ったときに、任意の処理を実行するように設定できます。通常のスクリプトでは、予期しない中断が起こるとそのまま異常終了してしまいますが、trapを使えば、終了処理を行ったり、ログを記録したりすることができます。

trap 'コマンド群' シグナル

たとえば、以下のように記述すると、Ctrl+C(SIGINT)を押した際に「割り込みを検知しました」と表示されます。

trap 'echo "割り込みを検知しました"' INT

シグナルとは?trapと関係する代表的なシグナル一覧

シグナルとは、プロセスに対して送る通知のようなもので、プロセスの制御に使われます。trapで扱う代表的なシグナルは以下の通りです。

シグナル説明
INT割り込み(Ctrl+C)
TERM終了要求
HUPハングアップ(端末切断など)
EXITスクリプトの終了時
ERRコマンド失敗時(set -e 使用時)
QUITコアダンプ付きの終了(Ctrl+\)

これらをtrapでキャッチして、任意の処理を定義できます。


trapコマンドの基本的な使い方

以下に、trapコマンドの書き方と基本的な使用例を紹介します。

例:一時ファイルを削除してから終了するスクリプト

#!/bin/bash

TEMP_FILE="/tmp/my_tempfile"

# 一時ファイル作成
touch $TEMP_FILE
echo "一時ファイルを作成しました:$TEMP_FILE"

# trapで終了処理を設定
trap 'echo "終了処理中..."; rm -f $TEMP_FILE; echo "一時ファイルを削除しました"; exit' EXIT

# 無限ループ(終了まで何か作業)
while true; do
echo "作業中... Ctrl+Cで終了"
sleep 2
done

このスクリプトでは、スクリプトが終了するタイミング(正常終了、Ctrl+Cなど)で一時ファイルを削除する処理をtrapで定義しています。


複数のシグナルをまとめて扱う

trapでは、複数のシグナルに同じ処理を割り当てることも可能です。

trap 'echo "終了または割り込みを検知"; cleanup' INT TERM

この例では、INT(Ctrl+C)とTERM(終了要求)のどちらかが来たときに、cleanup関数を実行するようにしています。


trapで関数を呼び出す

trapでは処理内容に関数を使うこともできます。スクリプトが長くなる場合や、処理を複数まとめたいときに便利です。

bashコピーする編集するcleanup() {
    echo "クリーンアップ処理中..."
    rm -f /tmp/tempfile
    echo "完了しました"
}

trap cleanup EXIT

このように、処理を関数化することで、可読性や保守性が向上します。


応用:ログ記録+クリーンアップのトラップ例

以下は、ログファイルに処理結果を書きつつ、一時ファイルを削除して終了する例です。

#!/bin/bash

LOGFILE="/tmp/script.log"
TEMPFILE="/tmp/tempfile.txt"

touch "$TEMPFILE"
echo "作業開始" >> "$LOGFILE"

trap '{
echo "終了時刻: $(date)" >> "$LOGFILE"
echo "一時ファイルを削除します" >> "$LOGFILE"
rm -f "$TEMPFILE"
echo "終了しました"
}' EXIT

echo "スクリプト実行中..." >> "$LOGFILE"
sleep 10

このスクリプトでは、スクリプトが終了する際に、ログを記録しつつファイルの削除を行っています。システム運用やサーバー管理においてよくある実装です。


trapを解除する方法

一度設定したtrapを解除するには、以下のように記述します。

trap - シグナル

もしくは、すべてのtrapを解除したいときは以下のようにします。

trap - EXIT INT TERM

これで、それ以降のシグナルに対するtrapの影響が無効になります。


よくある落とし穴と注意点

trapを使う際の注意点もいくつかあります。

  1. 子プロセスにはtrapが継承されない
    trapは現在のシェルプロセスにのみ有効です。subshell(括弧で囲った処理)では反映されないことに注意しましょう。
  2. シグナル名は大文字で書く
    trap '...' intのように小文字で書くと動作しないことがあります。INTTERMのように大文字で書くのが正解です。
  3. 処理の中でexitしないと、ループが続くことがある
    whileforループ内でtrapしたとき、適切にexitしないと処理が終わらないことがあるので、明示的に終了するようにしましょう。

まとめ

trapコマンドは、シェルスクリプトにおけるエラーハンドリングやリソースのクリーンアップに欠かせない重要なツールです。予期しない中断や異常終了からスクリプトを守るために、ぜひ積極的に活用してみてください。基本的な使い方から、関数化、ログ処理まで、状況に応じてtrapをうまく使い分ければ、より堅牢で実用的なスクリプトを書くことができるようになります。

upandup

Web制作の記事を中心に、暮らし、ビジネスに役立つ情報を発信します。 アフィリエイトにも参加しています。よろしくお願いいたします。