Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

wait / trap

『wait』はバックグラウンドプロセスの終了を待ちます。『trap』はシグナルやシェルの終了イベントをキャッチして任意の処理を実行します。スクリプトのクリーンアップ処理や安全な終了処理の実装に欠かせません。

構文
# wait(プロセスの待機)
wait           # 全バックグラウンドジョブが終了するまで待つ
wait $PID      # 指定した PID が終了するまで待つ
wait %ジョブ番号  # 指定したジョブが終了するまで待つ

# trap(シグナルのキャッチ)
trap '処理' シグナル名...
trap '処理' EXIT     # スクリプト終了時に必ず実行
trap '処理' INT      # Ctrl+C(SIGINT)をキャッチ
trap '処理' TERM     # SIGTERM をキャッチ
trap '処理' ERR      # コマンドがエラーになったときにキャッチ

# trap の解除
trap - シグナル名    # デフォルト動作に戻す
trap '' シグナル名   # シグナルを無視する
コマンド一覧
コマンド/シグナル概要
wait全バックグラウンドジョブが完了するまで待ちます。
wait $PID指定した PID のプロセスが終了するまで待ちます。終了ステータスを返します。
trap '処理' EXITスクリプトの終了時(正常・異常問わず)に実行されます。一時ファイルの削除に便利です。
trap '処理' INTCtrl+C が押されたときに実行されます。
trap '処理' TERMSIGTERM を受信したときに実行されます。
trap '処理' ERRコマンドが 0 以外の終了ステータスを返したときに実行されます。
trap '処理' HUPSIGHUP を受信したときに実行されます(端末切断・設定再読み込み)。
trap '' INTCtrl+C を無視します(重要な処理中の誤操作防止)。
サンプルコード

『trap ... EXIT』で一時ファイルを確実に削除します。正常終了・エラー終了・Ctrl+C のいずれでもクリーンアップが実行されます。

#!/bin/bash
tmpfile=$(mktemp /tmp/myapp.XXXXXX)
echo "一時ファイル: $tmpfile"

trap 'rm -f "$tmpfile"; echo "クリーンアップ完了"' EXIT

echo "処理データ" > "$tmpfile"
cat "$tmpfile"
一時ファイル: /tmp/myapp.aB3xYz
処理データ
クリーンアップ完了

Ctrl+C(SIGINT)や SIGTERM を捕捉して安全に終了する例です。クリーンアップ処理を関数にしておくと管理しやすくなります。

#!/bin/bash
cleanup() {
    echo ""
    echo "割り込みを検出しました。安全に終了します..."
    exit 0
}
trap cleanup INT TERM

echo "Ctrl+C で終了できます(3秒後に自動終了)"
sleep 3
echo "正常終了"
Ctrl+C で終了できます(3秒後に自動終了)
正常終了

『wait』と『trap』を組み合わせた並列処理の例です。複数のワーカーをバックグラウンドで起動し、個別に終了ステータスを確認します。

#!/bin/bash
worker() {
    local id=$1
    sleep $(( RANDOM % 3 + 1 ))
    echo "ワーカー $id 完了"
    return 0
}

pids=()
for i in {1..3}; do
    worker $i &
    pids+=($!)
done

echo "全ワーカーの完了を待っています..."
for pid in "${pids[@]}"; do
    wait "$pid"
    echo "PID $pid の終了ステータス: $?"
done
echo "全ワーカー完了"
全ワーカーの完了を待っています...
ワーカー 2 完了
ワーカー 3 完了
ワーカー 1 完了
PID 12345 の終了ステータス: 0
PID 12346 の終了ステータス: 0
PID 12347 の終了ステータス: 0
全ワーカー完了
概要

『trap ... EXIT』はスクリプトが正常終了・エラー終了・SIGTERM・SIGINT のどの場合でも実行されます(SIGKILL は除く)。一時ファイルの削除・ロックファイルの解除・ログへの書き込みなどクリーンアップ処理の定番パターンです。本番スクリプトには必ず書くことを推奨します。

trap のハンドラを関数にしておくと複数のシグナルに同じ処理を登録でき、後から変更もしやすくなります。

バックグラウンド実行の詳細は &(バックグラウンド実行) を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。