하위 프로세스 중 하나가 코드! = 0로 끝나는 경우 해당 스크립트에서 생성 된 여러 하위 프로세스가 종료 코드! = 0을 반환하도록 bash 스크립트에서 대기하는 방법
간단한 스크립트 :
#!/bin/bash
for i in `seq 0 9`; do
doCalculations $i &
done
wait
위의 스크립트는 생성 된 10 개의 하위 프로세스를 모두 기다리지 만 종료 상태는 항상 0입니다 (참조 help wait
). 이 스크립트를 수정하여 생성 된 하위 프로세스의 종료 상태를 발견하고 하위 프로세스 중 하나가 코드! = 0으로 끝나면 종료 코드 1을 반환하도록하려면 어떻게해야합니까?
서브 프로세스의 PID를 수집하는 것보다 더 나은 해결책이 있습니까? 순서대로 기다렸다가 종료 상태를 합산합니까?
답변
wait
또한 (선택적으로) 프로세스의 PID를 기다리며 $! 백그라운드에서 시작된 마지막 명령의 PID를 얻습니다. 생성 된 각 하위 프로세스의 PID를 배열에 저장하도록 루프를 수정 한 다음 각 PID에서 다시 대기합니다.
# run processes and store pids in array
for i in $n_procs; do
./procs[${i}] &
pids[${i}]=$!
done
# wait for all pids
for pid in ${pids[*]}; do
wait $pid
done
답변
http://jeremy.zawodny.com/blog/archives/010717.html :
#!/bin/bash
FAIL=0
echo "starting"
./sleeper 2 0 &
./sleeper 2 1 &
./sleeper 3 0 &
./sleeper 2 0 &
for job in `jobs -p`
do
echo $job
wait $job || let "FAIL+=1"
done
echo $FAIL
if [ "$FAIL" == "0" ];
then
echo "YAY!"
else
echo "FAIL! ($FAIL)"
fi
답변
다음은를 사용하는 간단한 예 wait
입니다.
일부 프로세스를 실행하십시오.
$ sleep 10 &
$ sleep 10 &
$ sleep 20 &
$ sleep 20 &
그런 다음 wait
명령으로 기다리십시오 .
$ wait < <(jobs -p)
또는 wait
모두를 위해 (논쟁없이).
백그라운드의 모든 작업이 완료 될 때까지 기다립니다.
경우 -n
옵션이 제공되어, 다음 작업에 대한 대기 종료 및 종료 상태를 반환합니다.
help wait
및 help jobs
구문을 참조하십시오 .
그러나 단점은 마지막 ID의 상태에서만 반환되므로 각 하위 프로세스의 상태를 확인하여 변수에 저장해야한다는 것입니다.
또는 계산 기능을 사용하여 오류 발생시 (빈 또는 실패한 로그가있는) 일부 파일을 생성 한 다음 해당 파일이 존재하는지 확인
$ sleep 20 && true || tee fail &
$ sleep 20 && false || tee fail &
$ wait < <(jobs -p)
$ test -f fail && echo Calculation failed.
답변
GNU Parallel이 설치되어 있다면 다음을 수행 할 수 있습니다.
# If doCalculations is a function
export -f doCalculations
seq 0 9 | parallel doCalculations {}
GNU Parallel은 종료 코드를 제공합니다.
-
0-모든 작업이 오류없이 실행되었습니다.
-
1-253-일부 작업이 실패했습니다. 종료 상태는 실패한 작업 수를 제공합니다.
-
254-253 개 이상의 작업이 실패했습니다.
-
255-기타 오류
자세한 내용은 소개 비디오를 참조하십시오 : http://pi.dk/1
답변
어떻습니까?
#!/bin/bash
pids=""
for i in `seq 0 9`; do
doCalculations $i &
pids="$pids $!"
done
wait $pids
...code continued here ...
최신 정보:
여러 의견 제시자가 지적한 것처럼 위의 과정은 계속하기 전에 모든 프로세스가 완료되기를 기다립니다.하지만 프로세스 중 하나가 실패하면 종료하지 않고 실패하지 않습니다. :
#!/bin/bash
pids=""
RESULT=0
for i in `seq 0 9`; do
doCalculations $i &
pids="$pids $!"
done
for pid in $pids; do
wait $pid || let "RESULT=1"
done
if [ "$RESULT" == "1" ];
then
exit 1
fi
...code continued here ...
답변
지금까지 내가 생각해 낸 내용은 다음과 같습니다. 아이가 종료되면 잠자기 명령을 중단하여 WAITALL_DELAY
사용법 에 맞출 필요가 없도록하는 방법을 알고 싶습니다 .
waitall() { # PID...
## Wait for children to exit and indicate whether all exited with 0 status.
local errors=0
while :; do
debug "Processes remaining: $*"
for pid in "$@"; do
shift
if kill -0 "$pid" 2>/dev/null; then
debug "$pid is still alive."
set -- "$@" "$pid"
elif wait "$pid"; then
debug "$pid exited with zero exit status."
else
debug "$pid exited with non-zero exit status."
((++errors))
fi
done
(("$#" > 0)) || break
# TODO: how to interrupt this sleep when a child terminates?
sleep ${WAITALL_DELAY:-1}
done
((errors == 0))
}
debug() { echo "DEBUG: $*" >&2; }
pids=""
for t in 3 5 4; do
sleep "$t" &
pids="$pids $!"
done
waitall $pids
답변
이것을 병렬화하려면 …
for i in $(whatever_list) ; do
do_something $i
done
이것을 번역하십시오 …
for i in $(whatever_list) ; do echo $i ; done | ## execute in parallel...
(
export -f do_something ## export functions (if needed)
export PATH ## export any variables that are required
xargs -I{} --max-procs 0 bash -c ' ## process in batches...
{
echo "processing {}" ## optional
do_something {}
}'
)
- 한 프로세스에서 오류가 발생 하면 다른 프로세스를 방해하지 않지만 시퀀스에서 전체적으로 종료 코드가 0이 아닙니다 .
- 특정 경우에 함수 및 변수 내보내기가 필요할 수도 있고 필요하지 않을 수도 있습니다.
--max-procs
원하는 병렬 처리량을 기준으로 설정할 수 있습니다 (0
“한 번에 모두”를 의미 함).- GNU Parallel 은 대신 사용되는 몇 가지 추가 기능을 제공
xargs
하지만 항상 기본적으로 설치되는 것은 아닙니다. for
때문에 루프는이 예에서 꼭 필요한 것은echo $i
근본적으로 단지 출력을 재생한다$(whatever_list
).for
키워드를 사용하면 현재 상황을 좀 더 쉽게 알 수 있다고 생각합니다 .- 배쉬 문자열 처리는 혼란 스러울 수 있습니다. 작은 따옴표를 사용하면 사소한 스크립트를 래핑하는 데 가장 효과적이라는 것을 알았습니다.
- Bash 병렬 처리에 대한보다 직접적인 접근 방식과 달리 전체 작업 (^ C 또는 유사 항목 사용)을 쉽게 중단 할 수 있습니다 .
간단한 작업 예는 다음과 같습니다.
for i in {0..5} ; do echo $i ; done |xargs -I{} --max-procs 2 bash -c '
{
echo sleep {}
sleep 2s
}'