スクリプトまたはスクリプトが作成するバックグラウンドジョブのいずれかでエラーが発生した場合は、bashスクリプトを終了します

ダニー・デロット

バックグラウンド

同じディレクトリにある半ダースのプロジェクトを構築するプロセスを自動化するbashスクリプトに取り組んでいます。各プロジェクトには、プロジェクトをビルドするために実行する2つのスクリプトがあります。

npm install
npm run build

最初の行は、npmからすべての依存関係をフェッチします。この手順には最も時間がかかり、プロジェクトは依存関係を同時にフェッチできるため、バックグラウンドジョブを使用してすべてを並行してフェッチしています。(例:npm install &

2行目では、これらの依存関係を使用してプロジェクトをビルドします。これはすべてのステップ1が終了した後に発生する必要があるためwait、その間にコマンドを実行しています。以下のコードスニペットを参照してください。

質問

バックグラウンドジョブのいずれかでエラーが発生した場合、またはnpm run buildその後に発生しステップで、スクリプトを終了させたいのですが。

私は使用set -eしていますが、これはバックグラウンドジョブには適用されないため、1つのプロジェクトがその依存関係のインストールに失敗した場合、他のすべては続行されます。

これが私のスクリプトが今どのように見えるかの簡単な例です。

build.sh

set -e

DIR=$PWD

for dir in ./projects/**/
do
    echo -e "\033[4;32mInstalling $dir\033[0m"
    cd $dir
    npm install & # takes a while, so do this in parallel
    cd $DIR
done

wait # continue once the background jobs are completed

for dir in ./projects/**/
do
    cd $dir
    echo -e "\033[4;32mBuilding $dir\033[0m"
    npm run build # Some projects use other projects, so build them in series
    cd $DIR
    echo -e "\n"
done

繰り返しになりますが、エラーが発生した場合にスクリプトで何も実行し続けたくありません。これは、親ジョブとバックグラウンドジョブの両方に当てはまります。これは可能ですか?

チャールズ・ダフィー

バックグラウンドジョブのPIDを収集します。次に、を使用waitしてそれぞれの終了ステータスを収集し、そのループでポーリングされたPIDがゼロ以外の場合に最初に終了します。

install_pids=( )
for dir in ./projects/**/; do
  (cd "$dir" && exec npm install) & install_pids+=( $! )
done
for pid in "${install_pids[@]}"; do
  wait "$pid" || exit
done

上記は単純ですが、注意点があります。リストの後半のアイテムがリストの前のアイテムの前にゼロ以外で終了する場合、リストのそのポイントがポーリングされるまで、これは監視されません。この警告を回避するには、リスト全体を繰り返し繰り返すことができます。

install_pids=( )
for dir in ./projects/**/; do
  (cd "$dir" && exec npm install) & install_pids+=( $! )
done
while (( ${#install_pids[@]} )); do
  for pid_idx in "${!install_pids[@]}"; do
    pid=${install_pids[$pid_idx]}
    if ! kill -0 "$pid" 2>/dev/null; then # kill -0 checks for process existance
      # we know this pid has exited; retrieve its exit status
      wait "$pid" || exit
      unset "install_pids[$pid_idx]"
    fi
  done
  sleep 1 # in bash, consider a shorter non-integer interval, ie. 0.2
done

ただし、これはポーリングするため、余分なオーバーヘッドが発生します。これは、SIGCHLDをjobs -nトラップし、トラップがトリガーされたときに(前回のポーリング以降にステータスが変更されたジョブのリストを取得するために)参照することで回避できます

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ