私はバックグラウンドで複数のコマンドを同時に実行し、すべてのコマンドが完了するのを待つスクリプトを作成しています。
#!/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
別のアプローチは、ほとんどの実装でサポートされているオプションを使用することです。sh
POSIX規格の次のバージョンに登場する予定です。:
#! /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ベースのシェルはすでにこれをサポートしています。