一部のサーバーを起動するには、次の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
ここにはいくつかの質問があります。
- サブシェルのコマンドが失敗すると、スクリプト全体が中断されます。
- 発生するエラーの可視性を高めます。
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
。)