스크립트의 한 프로세스가 실패하는 경우 대기(bash posix)를 사용하여 실패하세요.

스크립트의 한 프로세스가 실패하는 경우 대기(bash posix)를 사용하여 실패하세요.

저는 백그라운드에서 여러 명령을 동시에 실행한 다음 모든 명령이 완료될 때까지 기다리는 스크립트를 작성하고 있습니다.

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

문제는 이러한 프로세스 중 하나 이상이 실패하면 계속 진행된다는 것입니다. 이 모든 명령을 동시에 실행하고 하나 이상의 명령이 실패했는지 확인하려면 어떻게 해야 합니까?

답변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 기반 쉘은 이미 이를 지원합니다.

관련 정보