Bash – バックグラウンドプロセス終了の待機

Bash – バックグラウンドプロセス終了の待機

一部のサーバーを起動するには、次のbashスクリプトがあります。

services=(
    account-service
    reminder-service
    activity-service
    socket-service
    chat-service
    web-app
)


for s in "${services[@]}"; do

 (
   set -e;
   cd "$s"
   git pull
   npm start || exit 1 # always fails
 ) &

 sleep 1;

done

wait;

時にはgit pullコマンドが失敗します。しかし、欠陥はログの深いところにあり、必ずしも明確ではありません。サブシェルのコマンドの1つが1で終了した場合、スクリプト全体をどのように中断しますか?

答え1

さて、おそらくwait次のように文を変更してみてください。

while true; do
    wait -n || exit 1          # if one of the background jobs failed, abort
    [[ "$(jobs)" ]] && break   # exit this loop if no more jobs
done

完全にテストされていません。jobsこれが非対話型シェルで期待どおりに機能するかどうかはわかりません。

答え2

ここにはいくつかの質問があります。

  1. サブシェルのコマンドが失敗すると、スクリプト全体が中断されます。
  2. 発生するエラーの可視性を高めます。

2回目から始めます。この質問には回答のシードが含まれています。エラーは記録されますが、ログの内容はユーザーには明確ではありません。したがって、エラーは一時ログファイルに書き込まれ、最後に表示されます。

サービス=(
    アカウントサービス
    通知サービス
    イベントサービス
    ソケットサービス
    チャットサービス
    Webアプリケーション
)
エラーファイル=$(mktemp)

"${services[@]}" の for s;
   セットです。
   CD "$s"
   子供を引っ張る  || {
        echo "$s" >> "$errfile"
        1番出口
   }
   エコ「$cmd」|
 )&
 睡眠1
完璧

待つ

if [ -s "$errfile" ]
それから
        echo "次のサービスにエラーがあります:"
        猫 "$errfile"
フィリピン諸島
rm -f "$errfile"

問題#1を解決する最も簡単な方法は、サブシェルのコードを定期的にチェックし、[ -s "$errfile" ]問題が発生した場合はそれ自体を停止することです。より野心的なアプローチは、基本(親)プロセスが子プロセスのPIDを追跡し、そのプロセスにシグナルを送信することです。がないかどうかはわかりませんwait -n。 (おそらくエラーのある子が親に信号を送ってくださいwait。)

関連情報