아래 코드에서 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 xtrace
is -x
, -o errexit
is -e
( pipefail
, ksh에서, 이제 대부분의 다른 쉘에서 발견되며 곧 표준이 될 것이며 대부분의 쉘에는 해당하는 단일 문자가 없습니다)
errexit
즉, 처리되지 않은 명령이 실패하면 스크립트가 종료됩니다. pipefail
즉, 파이프라인의 구성 요소 중 하나라도 실패하면 전체 파이프라인이 실패한 것으로 간주됩니다(그렇지 않으면 가장 오른쪽 구성 요소만 고려됨).
따라서 echo 'x' |grep '1x' | wc -l
이러한 3개 명령( echo
, grep
및 ) wc
중 하나라도 실패하면 파이프라인이 실패합니다.
여기서는 출력에 포함된 행을 grep
찾을 수 없으므로 실패가 보고됩니다. 이는 동일한 실패한 종료 상태로 실행 중인 서브쉘을 종료하기 때문입니다. 결과 할당도 실패하고 스크립트를 실행하는 셸이 종료됩니다.1x
echo
errexit
$(...)
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
)은 매우 취약한 기능입니다. 가장 간단한 스크립트 이외의 용도로 사용하거나 대신 수동 오류 처리를 수행하는 것을 권장하지 않습니다. 다른 프로그래밍 언어에서와 마찬가지로 스크립트의 모든 명령줄이 실패하면 어떤 일이 일어날지 자문해 보세요.