制御演算子「&」を使用してバックグラウンド実行する
コマンドの後ろに制御演算子「&」をつけて実行した場合、シェルはそのコマンドをサブシェル内でバックグラウンドで実行します。
sleep 0.1 &
echo "ステータス=$? プロセスID=$!"
「$!」は最後に実行されたバックグラウンドコマンドのプロセスIDに置換されます。コマンドをバックグラウンドで実行した場合、シェルはコマンドの終了を待たずに終了ステータス 0 を返却します。
ls ./not_exist &
echo "ステータス=$? プロセスID=$!"
バックグラウンドで実行処理の終了を待つ
バックグラウンドで実行されたコマンドは非同期で実行されるため、呼び出し元の処理はバックグラウンドで実行した処理の終了を待ちません。
# バックグラウンドで実行した処理の done が出力される前に
# メイン処理の done が出力される
{ sleep 0.1; echo ' task1) done'; } &
{ sleep 0.1; echo ' task2) done'; } &
jobs -l
echo 'main) done'
バックグラウンドで実行した処理の終了を待つには wait コマンドを使用します。
{ sleep 0.1; echo ' task1) done'; } &
{ sleep 0.1; echo ' task2) done'; } &
jobs -l
echo "main) wait"
wait
echo "main) wait done status=$?"
jobs -l
echo 'main) done'
wait コマンドには終了を待機する処理のプロセスIDまたはジョブIDを指定することができます。指定しない場合はすべてのバックグラウンド処理の終了を待ちます。
{ sleep 0.1; echo ' task1) done'; } &
task1=$!
{ sleep 0.2; echo ' task2) done'; } &
jobs -l
echo "main) wait pid=${task1}"
wait "${task1}"
echo "main) wait pid=${task1} done status=$?"
echo 'main) done'
wait コマンドの終了ステータスについて
wait コマンドに終了を待機する処理のプロセスIDやジョブIDを指定して実行した場合の終了ステータスは終了を待機した処理の終了ステータスになります。
{ sleep 0.1; echo ' task) done'; exit 99; } &
pid=$!
jobs -l
echo "main) wait pid=$pid"
wait $pid
status=$?
echo "main) wait pid=$pid done"
jobs -l
echo "main) wait pid=$pid status=$status"
echo 'main) done'
jobs -l
引数を指定せずに wait コマンドでバックグラウンドプロセスの終了を待機した場合、wait コマンドの終了ステータスは 0 になります。
{ sleep 0.1; echo ' task1) done'; exit 91; } &
{ sleep 0.2; echo ' task2) done'; exit 92; } &
jobs -l
echo "main) wait"
wait
status=$?
echo "main) wait status=$status"
echo 'main) done'
jobs -l
wait コマンドに存在しないプロセスIDやジョブIDを指定した場合、wait コマンドの終了ステータスは 127 になります。
wait 9999
status=$?
echo "wait done status=$status"
wait コマンドにジョブIDを指定する場合は「%ジョブ番号」の形で指定します。
{ sleep 0.1; echo ' job1) done'; exit 1; } &
{ sleep 0.2; echo ' job2) done'; exit 2; } &
jobs -l
wait %1
status1=$?
echo "main) wait job1 status=$status1"
wait %2
status2=$?
echo "main) wait job2 status=$status2"
jobs -l
echo 'main) done'
バックグラウンドプロセスを強制終了させる
バックグラウンド処理は kill コマンドで強制終了させることができます。
{ sleep 1; echo ' task) done'; } &
pid=$!
jobs -l
echo "main) task kill $pid"
kill $pid
kill_status=$?
echo "main) task killed status=$kill_status"
wait $pid
wait_status=$?
echo "main) task wait $pid status=$wait_status"
jobs -l
強制終了させたバックグラウンド処理の終了ステータスを wait コマンドで取得したところ 143 でした。終了ステータスが 143 なので SIGTERM (143 - 128 = 15) を送られて終了していることが確認できました。
kill -l