저는 백그라운드에서 여러 명령을 동시에 실행한 다음 모든 명령이 완료될 때까지 기다리는 스크립트를 작성하고 있습니다.
#!/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
또 다른 접근 방식은 대부분의 구현 에서 지원되는 옵션을 사용하는 것입니다.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 기반 쉘은 이미 이를 지원합니다.