zsh
스크립트에는 긴 명령 파이프라인이 있습니다.
pv /dev/sda > sda.raw | sha256sum > sda.raw.sha256 | cut -c61-64 | read SHASUM
if
모든 명령이 성공적으로 종료되었는지 문 내부에서 어떻게 확인할 수 있나요 ?
알아요 ${pipestatus[@]}
. 하지만 배열이에요. 그래서 각 요소를 개별적으로 확인해야 합니다.
${pipestatus[@]}
포함된 내용만 확인하는 바로가기가 있습니까 0
?
고쳐 쓰다:
몇 가지 이상한 동작을 발견했습니다.
테스트를 위해 빠르게 채워지도록 작은 파일 시스템(10MB)을 설정했습니다.
#!/bin/zsh
set -o pipefail
if pv /dev/zero > loop/file ; then
echo OK
else
echo FAIL
fi
예상대로 "FAIL"을 인쇄하면서 다음 오류가 발생합니다.
pv: write failed: No space left on device
그런데 pv 명령을 약간 변경하면 갑자기 오류가 인쇄되지 않고 pv 명령이 무한정 실행되는 것처럼 보입니다(장치에 남은 공간이 없음에도 불구하고).
#!/bin/zsh
set -o pipefail
if pv /dev/zero > loop/file | sha256sum ; then
echo OK
else
echo FAIL
fi
답변1
두 가지 옵션:
pipefail
이 옵션이 ksh() 에서 설정되면set -o pipefail
파이프라인의 종료 상태는 가장 오른쪽에 실패한 파이프라인 구성 요소의 종료 상태가 됩니다.set -o pipefail if ! A | B | C; then echo at least one of the commands failed. fi
검색에서 0이 아닌 값을 찾습니다
$pipestatus
. 이extendedglob
옵션을 활성화 하면 가장 왼쪽의 실패한 파이프라인 구성 요소와 가장 오른쪽의 실패한 파이프라인 구성 요소 의 종료 상태가 반환되므로$pipestatus[(r)^0]
(또는$pipestatus[(r)<1->]
not 필수 ) 다음을 수행할 수 있습니다.extendedglob
$pipestatus[(R)^0]
set -o extendedglob A | B | C if (( $pipestatus[(r)^0] )); then echo at least one of the commands failed. fi
또는
A | B | C if (( $pipestatus[(r)<1->] )); then echo at least one of the commands failed. fi
/
I
대신 아래 첨자 플래그를 사용하면 가장 오른쪽에 일치하는 요소의 인덱스를 얻을 수 있으므로 다음을 수행할 수 있습니다.r
R
I
A | B | C if (( failed = $pipestatus[(I)<1->] )); then echo component $failed failed. fi
${pipestatus:#0}
0 이외의 구성 요소로 확장되므로 다음을$pipestatus
수행할 수도 있습니다.A | B | C failed_statuses=( ${pipestatus:#0} ) if (( $#failed_statuses )); then echo "${#failed_statuses} command(s) failed. Statuses: $failed_statuses" fi