スクリプトの1つのプロセスが失敗した場合は、bash posixを使用して失敗してください。

スクリプトの1つのプロセスが失敗した場合は、bash posixを使用して失敗してください。

私はバックグラウンドで複数のコマンドを同時に実行し、すべてのコマンドが完了するのを待つスクリプトを作成しています。

#!/bin/sh -fx
./p1 &
./p2 &
./p3 &
./p4 &
./p5 &
wait

問題は、これらのプロセスの1つ以上が失敗した場合に続行することです。これらすべてのコマンドを同時に実行し、1つ以上のコマンドが失敗したことを確認するにはどうすればよいですか?

ベストアンサー1

個々のPIDが終了状態を取得するのを待つことができます。

#! /bin/sh -
set -o xtrace -o noglob

./p1 & p1=$!
./p2 & p2=$!
./p3 & p3=$!
./p4 & p4=$!
./p5 & p5=$!
fail=0
for pid in "$p1" "$p2" "$p3" "$p4" "$p5"; do
  wait "$pid" || fail=$(( fail + 1 ))
done
echo>&2 "$fail failed"
exit "$(( fail > 0 ))"

これらのプロセスが終了する順序で必ず待つ必要はありませんが、pidがすでに終了してから呼び出されたwait pid場合でも、pidの終了ステータスを取得するように努力する必要があります。wait

pipefail別のアプローチは、ほとんどの実装でサポートされているオプションを使用することです。shPOSIX規格の次のバージョンに登場する予定です。:

#! /bin/sh -
set -o xtrace -o noglob -o pipefail
alias r='<&3 3<&- >&4 4>&-'

die() { printf>&2 '%s\n' "$@"; exit 1; }

{
  r ./p1 | r ./p2 | r ./p3 | r ./p4 | r ./p5
} 3<&0 4>&1 || die "At least one of them failed"

パイプラインから始まりますが、パイプラインを使用しません。このrエイリアスを使用して、これらのプロセスのstdinとstdoutをfd 3と4に格納されている元の値に復元します。


残念ながらdashまだではありませんが、他のほとんどのAshベースのシェルはすでにこれをサポートしています。

おすすめ記事