バックグラウンド
同じディレクトリにある半ダースのプロジェクトを構築するプロセスを自動化する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]
コメントを追加