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