Bash 하위 쉘의 오류 처리

Bash 하위 쉘의 오류 처리

bash 코드를 작성 중인데 오류가 발생하면 스크립트가 종료되기를 원합니다. set -e 트릭은 훌륭하게 작동하지만 서브쉘에서는 작동하지 않습니다. 다음은 간단한 예입니다.

set -e

chmod a=r file.txt
x=`grep value file.txt | awk '{print $2*2}'`
echo "okay, x=$x"

chmod a= file.txt
x=`grep value file.txt | awk '{print $2*2}'`
echo "should never be printed"

이 예에서 두 번째 grep 명령은 0이 아닌 종료 상태로 실패하지만 서브셸은 여전히 ​​상태 0으로 완료되는 awk 명령을 실행합니다. 따라서 전체 서브셸의 종료 상태는 0이고 스크립트는 계속 실행됩니다.

웹 검색에는 set -e 제한 사항에 대한 여러 기사가 표시되지만 누구든지 깔끔한 해결 방법을 권장할 수 있습니까?

답변1

 x=`grep value file.txt | awk '{print $2*2}'`

두 번째 grep 명령은 0이 아닌 종료 상태로 실패하지만 서브셸은 여전히 ​​awk 명령을 실행합니다.

이것은 실제로 서브쉘과 관련이 없고 오히려 파이프가 작동하는 방식과 관련이 있습니다. 쉘 부팅둘 다파이프라인의 (모든) 명령은 동시에 실행되므로 오른쪽 명령이 시작될 때까지 왼쪽의 종료 상태도 알 수 없습니다.

예, 기본적으로 파이프의 종료 상태는 가장 오른쪽 명령의 종료 상태입니다. 일반적으로 이것은 파이프를 완성하여 가장 오른쪽 명령이 모든 입력을 읽지 않고 종료되고, 가장 왼쪽 명령이 현재 닫힌 파이프에 더 쓰려고 할 때 SIGPIPE 신호에 의해 종료되기 때문에 유용합니다.

나머지 데이터에는 실제로 관심이 없기 때문에 이것은 버그가 아닙니다. 다음과 같은 경우에만 확인하는 것을 고려 해보세요 zcat file.gz | grep -q xyz.xyz어딘가에데이터에서 적어도 한 번은.

어쨌든, 그들이 코멘트에서 말했듯이, set -o pipefail가장 오른쪽에 있는 것을 얻기 위해 많은 쉘(Bash, ksh, zsh, Busybox, 적어도)을 사용합니다.0이 아닌종료 상태는 전체 파이프라인의 종료 상태를 결정합니다.

단, grep오류가 발생한 경우뿐만 아니라 일치하는 행이 없는 경우에도 오류 상태가 반환된다는 점에 유의하세요. 이것이 버그로 간주되는 것을 원하지 않으면 더 많은 작업을 수행해야 합니다.

awk이 특별한 경우에는 패턴 일치를 수행 할 수도 있습니다 (예: ) x=$(awk '/value/ {print $2 * 2}' < file.txt). 파일을 읽을 수 없으면 오류와 함께 종료되어야 합니다.

관련 정보