ShellスクリプトでSignal Handlerを実装することで、スクリプトの実行中に特定のシグナルを受信した際の動作を制御できます。
例えば、Ctrl+C
による割り込み (SIGINT) を処理してクリーンアップ処理を実行したり、スクリプトを安全に終了させたりすることができます。
この記事では、trap
コマンドを使ってSignal Handlerを定義する方法と、
具体的な例をいくつか紹介します。
trap
コマンドの基本
trap
コマンドは、シグナルを受信した際に実行するコマンドを指定するために使用します。基本的な構文は以下の通りです。
trap 'command' signal
-
command
: シグナルを受信した際に実行されるコマンド。クォートで囲む必要があります。 -
signal
: 処理対象のシグナルの名前または番号。複数のシグナルをスペース区切りで指定することも可能です。
シグナルの例
よく使われるシグナルには以下のようなものがあります。
- SIGINT (2): Ctrl+Cによる割り込み。
-
SIGTERM (15):
kill
コマンドによる終了要求 (デフォルト)。 - SIGHUP (1): 制御端末の切断。
- SIGUSR1 (10): ユーザー定義シグナル1。
- SIGUSR2 (11): ユーザー定義シグナル2。
- EXIT (0): スクリプトの終了時。
使用例
1. Ctrl+Cによる割り込みを処理する
#!/bin/bash
trap 'echo "Ctrl+Cが押されました。クリーンアップ処理を実行..."; exit 1' INT
# 時間のかかる処理
for i in {1..10}; do
sleep 1
echo "処理中... $i"
done
echo "処理完了"
このスクリプトでは、Ctrl+C (SIGINT)
を受信すると、"Ctrl+Cが押されました。クリーンアップ処理を実行..."
が出力され、スクリプトは終了コード1で終了します。 sleep
コマンドで模擬された時間のかかる処理中でも、Ctrl+C
で中断できます。
2. 複数のシグナルを処理する
#!/bin/bash
cleanup() {
echo "クリーンアップ処理を実行..."
rm -f /tmp/tempfile.txt
}
trap cleanup INT TERM EXIT
touch /tmp/tempfile.txt
# 時間のかかる処理
for i in {1..10}; do
sleep 1
echo "処理中... $i"
done
echo "処理完了"
この例では、cleanup
という関数を定義し、SIGINT、SIGTERM、EXITの3つのシグナルに対して同じ処理を実行するように設定しています。 これにより、Ctrl+C
、kill
コマンド、通常のスクリプト終了時にクリーンアップ処理が実行されます。
3. シグナルを無視する
#!/bin/bash
trap '' INT
# Ctrl+Cを無視する
while true; do
sleep 1
echo "処理中..."
done
この例では、trap '' INT
とすることで、SIGINTを無視するように設定しています。 このスクリプトはCtrl+C
では停止できません。別のシグナル(例: kill -9 <PID>
) を送る必要があります。
4. デフォルトの動作に戻す
#!/bin/bash
trap 'echo "SIGINT received"' INT
sleep 5 # 最初はハンドラが実行される
trap - INT # デフォルトの動作に戻す
sleep 5 # 次のSIGINTはスクリプトを終了させる
trap - シグナル
とすることで、指定したシグナルに対するハンドラを解除し、デフォルトの動作に戻すことができます。
これらの例を参考に、trap
コマンドを使ってスクリプトの挙動をカスタマイズし、より堅牢なスクリプトを作成しましょう。 シグナルハンドラは、一時ファイルの削除、リソースの解放、ログの書き込みなど、様々なクリーンアップ処理に活用できます。
まとめ
trap
コマンドを使用することで、Shellスクリプトでシグナルを処理し、予期せぬイベントに対する適切な対応が可能になります。 シグナルハンドラを適切に実装することで、スクリプトの安定性と信頼性を向上させることができます。