파이프라인에서 최종이 아닌 명령의 종료 상태를 어떻게 캡처합니까? [복사]

파이프라인에서 최종이 아닌 명령의 종료 상태를 어떻게 캡처합니까? [복사]

파이프라인 어딘가에서 발생하는 명령의 종료 상태를 캡처하고 싶습니다.앞으로최종 위치. 예를 들어 파이프라인이 다음과 같다면

command_1 ... | command_2 ... | command_3 ... | ... | command_n

command_1... , command_2또는 등 의 종료 상태를 캡처하는 방법을 알고 싶습니다 . (물론 command_3캡쳐된 종료상태는 간단합니다.)command_n

또한 중요한 경우 이 파이프는 zsh 쉘 함수 내부에서 발생합니다.


command_1다음과 같은 것을 사용하여 종료 상태를 캡처 하려고했습니다 .

function_with_pipeline () {

    local command_1_status=-999999  # sentinel value

    { command_1 ...; command_1_status=$? } | command_2 ... | ... | command_n
    ...

}

...하지만 파이프라인을 실행한 후에도 command_1_status변수 값은 여전히 ​​센티널 값입니다.


FWIW, 다음은 파이프라인에 두 개의 명령만 있는 작업 예입니다.

foo ... | grep ...

foo이 예에 대해 정의된 함수는 다음과 같습니다.

foo () {

    (( $1 & 1 )) && echo "a non-neglible message"
    (( $1 & 2 )) && echo "a negligible message"
    (( $1 & 4 )) && echo "error message" >&2

    return $(( ( $1 & 4 ) >> 2 ))
}

foo목표는 파이프라인에서 호출의 종료 상태를 캡처하는 것입니다.

이 함수는 function_with_pipeline이를 수행하기 위해 위에서 설명한 (궁극적으로 비효율적인) 전략을 구현합니다.

function_with_pipeline () {

    local foo_status=-999999  # sentinel value

    { foo $1; foo_status=$? } | grep -v "a negligible message"

    printf '%d\ndesired: %d; actual: %d\n\n' $1 $(( ( $1 & 4 ) >> 2 )) $foo_status

}

다음 루프는 이 function_with_pipeline기능을 실행합니다. 출력은 지역 변수의 값이 foo_status처음과 다르지 않게 종료됨을 보여줍니다.

for i in $(seq 0 7)
do
    function_with_pipeline $i
done
# 0
# desired: 0; actual: -999999
# 
# a non-neglible message
# 1
# desired: 0; actual: -999999
# 
# 2
# desired: 0; actual: -999999
# 
# a non-neglible message
# 3
# desired: 0; actual: -999999
# 
# error message
# 4
# desired: 1; actual: -999999
# 
# error message
# a non-neglible message
# 5
# desired: 1; actual: -999999
# 
# error message
# 6
# desired: 1; actual: -999999
# 
# error message
# a non-neglible message
# 7
# desired: 1; actual: -999999
#

local정의에서 선언을 생략하면 동일한 결과를 얻게 됩니다 foo_status.

답변1

특별한 배열이 있으니 시도해 보세요 pipestatus.zsh

command_1 ... | command_2 ... | command_3

그리고

echo $pipestatus[1] $pipestatus[2] $pipestatus[3]

귀하의 접근 방식이 작동하지 않는 이유는 각 파이프가 별도의 하위 쉘에서 실행되고 하위 쉘이 종료되면 자체 변수가 파괴되기 때문입니다.


PIPESTATUS참고로 (대문자) 형식 입니다 bash.

답변2

mispipe모든 쉘에서 작동합니다. 일반 파이프와 비교하여 구문은 다음과 같이 작동합니다.

mispipe true false ; echo $?  # returns exit code of 1st command `true`
true | false ; echo $?  # returns exit code of 2nd command `false`

산출:

0
1

프로그램이 2개 이상인 경우 수행할 작업:

# this still returns exit code of 1st command `true`
mispipe true 'false | false | false' ; echo $?

산출:

0

가시성이 부족함에도 불구하고 |여전히 파이프처럼 작동합니다.

yes | mispipe head 'wc -c'

산출:

     20

관련 정보