応用編:シグナル処理・バックグラウンドジョブ・並行実行
コマンドのバックグラウンド実行、wait を用いた並行タスクの同期、Unix シグナルの捕捉、および安全な終了処理(クリーンアップ)の設計を解説します。
バックグラウンド実行とジョブ制御
ターミナルを占有せずに時間のかかる処理を実行する機能です。
» バックグラウンド起動(&)
コマンドの末尾にアンパサンド(&)を付与すると、プロセスをバックグラウンドで開始し、即座にプロンプトが戻ります。
# 重い処理をバックグラウンドで実行
python train_model.py &
» ジョブ制御コマンド
jobs: 現在のシェルで管理されているバックグラウンドジョブ一覧を表示fg %1: 指定したジョブ番号のプロセスをフォアグラウンド(前面)に呼び戻すbg %1: 一時停止中のジョブをバックグラウンドで再開Ctrl + Z: 実行中のフォアグラウンドプロセスを一時停止(SIGTSTP)
wait による並行処理の同期
複数のバックグラウンドプロセスを同時に起動し、それらすべての完了を待ってから次の処理へ進む並行処理パターンです。
#!/usr/bin/env bash
set -euo pipefail
# 3つのタスクを並列にバックグラウンド実行
task_a() { sleep 3; echo "Task A done"; }
task_b() { sleep 2; echo "Task B done"; }
task_c() { sleep 1; echo "Task C done"; }
echo "Starting all tasks in parallel..."
task_a &
task_b &
task_c &
# すべてのバックグラウンドプロセスの完了を待機
wait
echo "All tasks finished."
個別プロセスの完了や成否を判定したい場合は、起動直後の $!(最新の PID)を配列等に退避し、wait $pid で個別に監視します。
Unix シグナルの捕捉(trap による後処理)
ユーザーによる強制中断(Ctrl + C)やシステム終了時にも、確実に一時ファイルを削除して安全に終了するためのシグナル処理です。
| シグナル名 | 番号 | 発生契機 |
|---|---|---|
INT | 2 | ユーザーが Ctrl + C を押下したとき |
TERM | 15 | kill コマンド等で終了が要求されたとき |
HUP | 1 | ターミナルウィンドウが閉じられたとき |
EXIT | 0 | 正常終了・異常終了を問わず、シェルが終了するとき |
» 一時ファイルの自動クリーンアップ
trap ... EXIT を設定すると、スクリプトがどのように終了した場合(途中で exit した場合やエラーが発生した場合も含む)でも、登録された後処理が確実に呼び出されます。
#!/usr/bin/env bash
set -euo pipefail
# 安全な一時ディレクトリを作成
TMP_DIR=$(mktemp -d "/tmp/my_app.XXXXXX")
# スクリプト終了時に必ず一時ディレクトリを削除
cleanup() {
echo "Cleaning up temporary files: $TMP_DIR"
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
# 処理本体
echo "Work data" > "$TMP_DIR/data.txt"
ロックファイルによる多重起動の防止
cron 等で定期実行されるスクリプトが前の処理の完了前に二重起動することを防ぐため、mkdir や flock を使用した排他制御を行います。
LOCK_FILE="/var/lock/my_script.lock"
# flock コマンドを用いた安全なファイルロック
exec 200>"$LOCK_FILE"
flock -n 200 || {
echo "Another instance is already running. Exiting." >&2
exit 1
}
echo "Lock acquired. Executing critical tasks..."