e 및 o를 설정할 때 쉘 스크립트가 올바르게 실행되지 않습니다.

e 및 o를 설정할 때 쉘 스크립트가 올바르게 실행되지 않습니다.

아래 코드에서 e와 o가 샘플링 시간을 설정하면 마지막 줄이 실행되지 않는 이유는 무엇입니까?

set -x
set -e
set -o pipefail

add=$(echo 'x' |grep '1x' | wc -l)
echo $add
echo '1'

답변1

단일 문자 옵션과 을 혼합하는 대신 -o option모든 항목에 긴 옵션 이름을 사용하는 것이 더 명확합니다.

set -o xtrace -o errexit -o pipefail

where -o xtraceis -x, -o errexitis -e( pipefail, ksh에서, 이제 대부분의 다른 쉘에서 발견되며 곧 표준이 될 것이며 대부분의 쉘에는 해당하는 단일 문자가 없습니다)

errexit즉, 처리되지 않은 명령이 실패하면 스크립트가 종료됩니다. pipefail즉, 파이프라인의 구성 요소 중 하나라도 실패하면 전체 파이프라인이 실패한 것으로 간주됩니다(그렇지 않으면 가장 오른쪽 구성 요소만 고려됨).

따라서 echo 'x' |grep '1x' | wc -l이러한 3개 명령( echo, grep및 ) wc중 하나라도 실패하면 파이프라인이 실패합니다.

여기서는 출력에 포함된 행을 grep찾을 수 없으므로 실패가 보고됩니다. 이는 동일한 실패한 종료 상태로 실행 중인 서브쉘을 종료하기 때문입니다. 결과 할당도 실패하고 스크립트를 실행하는 셸이 종료됩니다.1xechoerrexit$(...)var=$(...)

grep | wc -l이런 식으로 작성하는 것이 더 낫다 는 점에 유의하십시오 grep -c.

효과를 피하려면 errexit오류를 처리하면 됩니다.

그것은 다음과 같습니다:

var=$(echo x | grep -c 1x || : no match should not be a fatal error)

|| another command파이프라인 이후에는 실패가 쉘에 의해 수동으로 처리되는 것으로 간주되기 때문에 여기에는 errexit적용되지 않습니다 . 여기서 명령은 :아무 작업도 성공적으로 수행하지 않습니다( true아무 작업도 수행하지 않는 인수를 허용한다는 점만 제외).

처리 중인 파이프라인 오류입니다. 오류를 개별적으로 처리할 수도 있습니다 grep.

var=$(
  echo x | {
    grep 1x || : no match should not be a fatal error
  } | wc -l
) 

스크립트가 실패 echo하거나 wc종료되도록 허용합니다(여기에는 스크립트를 실행하기 위한 추가 하위 쉘이 포함됩니다 grep || :).

또는 할당 실패를 처리합니다.

var=$(echo x | grep -c 1x) || : no match should not be a fatal error

서브셸 내에서 비활성화할지 여부는 errexit셸과 해당 버전에 따라 다릅니다. 예를 들어 일부 쉘은 출력 x하고 다른 쉘은 빈 행을 출력합니다 sh -ec 'v=$(false; echo x) || true; echo "$v"'.

errexit(일명 set -e)은 매우 취약한 기능입니다. 가장 간단한 스크립트 이외의 용도로 사용하거나 대신 수동 오류 처리를 수행하는 것을 권장하지 않습니다. 다른 프로그래밍 언어에서와 마찬가지로 스크립트의 모든 명령줄이 실패하면 어떤 일이 일어날지 자문해 보세요.

관련 정보