트랩 기능에서 CHLD 서브쉘 구별

트랩 기능에서 CHLD 서브쉘 구별

이 bash 스크립트가 있습니다.

#!/usr/bin/env bash

set -m          # allow for job control
EXIT_CODE=0     # exit code of overall script

function foo() {
   echo "CHLD pid is $!"   # doesn't seem to be the expected pid
   echo "CHLD exit code is $?"  #exit code seems to pertain to some other process
   if [[ $? > 0 ]]; then
      echo "at least one test failed"
      EXIT_CODE=1
   fi
}

trap 'foo' CHLD

DIRN=$(dirname "$0")

commands=(
    "echo 'foo'; exit 1;"
    "echo 'bar'; exit 0;"
    "echo 'baz'; exit 2;"
)

clen=`expr "${#commands[@]}" - 1` # get length of commands - 1

for i in `seq 0 "$clen"`; do
    (echo "${commands[$i]}" | bash) &   # run the command via bash in subshell
    echo "$i ith command has been issued as a background job"
done

# wait for all to finish
wait

echo "EXIT_CODE => $EXIT_CODE"
exit "$EXIT_CODE"

여러 하위 쉘이 종료되어 종료 시 foo 함수가 트리거됩니다. 나는 foo 함수가 3개의 CHLD 이벤트만 캡처할 것이라고 예상했지만 실제로는 최소한 6개가 있었습니다.

CHLD함수 에서 발생하는 이벤트를 어떻게 구별하나요 foo?

예를 들어 위 스크립트의 출력은 다음과 같습니다.

CHLD exit code is 0
CHLD exit code is 0
CHLD exit code is 0
0 ith command has been issued as a background job
1 ith command has been issued as a background job
2 ith command has been issued as a background job
bar
baz
foo
CHLD exit code is 0
CHLD exit code is 0
CHLD exit code is 0
EXIT_CODE => 0

보시다시피 6개의 CHLD이벤트가 있지만 실제로는 3개만 관심이 있습니다. 또한 0,0,0이 아닌 1,0,2를 종료 코드로 간주해야 합니다.

그래서 두 가지 질문이 있습니다.

  1. foo 함수 내에서 종료되는 서브쉘을 식별하는 방법이 있습니까?
  2. 1 또는 2여야 하는 종료 코드가 0으로 표시되는 이유는 무엇입니까?

답변1

함수의 합계 값이 왜 $?문제가 아닌지 확실하지 않지만 다음 수정 사항은 다음과 같이 함수 내에서 합계 값을 사용하여 문제를 해결하는 것 같습니다.$!fooCHLDjobs -pfoo

#!/usr/bin/env bash

set -m          # allow for job control
EXIT_CODE=0     # exit code of overall script

function foo() {
    for job in `jobs -p`; do
        echo "PID => ${job}"
        if ! wait ${job} ; then
            echo "At least one test failed with exit code => $?" ;
            EXIT_CODE=1;
        fi
    done
}

trap 'foo' CHLD

DIRN=$(dirname "$0")

commands=(
    "{ echo 'foo' && exit 4; }"
    "{ echo 'bar' && exit 3; }"
    "{ echo 'baz' && exit 5; }"
)

clen=`expr "${#commands[@]}" - 1` # get length of commands - 1

for i in `seq 0 "$clen"`; do
    (echo "${commands[$i]}" | bash) &   # run the command via bash in subshell
    echo "$i ith command has been issued as a background job"
done

wait       # wait for all to finish

echo "EXIT_CODE => $EXIT_CODE"
exit "$EXIT_CODE"

관련 정보