단일 UNIX 사양 에서 의미set -e
를 설명 하는 데 사용되는 정확한 언어 는 다음과 같습니다.
이 옵션이 켜져 있으면 쉘 오류 결과에 나열된 이유로 단순 명령 이 실패 하거나 종료 상태 값> 0을 리턴하고 [조건부 또는 부정 명령]이 아닌 경우 쉘은 즉시 종료됩니다.
이러한 명령이 서브 쉘 에서 발생할 때 어떤 일이 발생하는지 모호합니다 . 실용적인 관점에서, 서브 쉘이 수행 할 수있는 모든 것은 종료하고 0이 아닌 상태를 상위 쉘로 리턴하는 것입니다. 부모 쉘이 차례로 종료되는지 여부는이 0이 아닌 상태가 부모 쉘에서 실패한 간단한 명령으로 변환되는지 여부에 따라 다릅니다.
이러한 문제가 발생한 사례 중 하나는 명령 대체 에서 0이 아닌 리턴 상태입니다 . 이 상태는 무시되므로 상위 쉘이 종료되지 않습니다. 이미 발견 했듯이 종료 상태를 고려하는 방법은 간단한 할당 에서 명령 대체를 사용하는 것입니다 . 그런 다음 할당 의 종료 상태는 할당에서 마지막 명령 대체의 종료 상태입니다 .
마지막 대체 상태 만 고려되므로 단일 명령 대체가있는 경우에만 의도 한대로 수행됩니다. 예를 들어, 다음 명령은 성공적입니다 (표준 및 내가 본 모든 구현에 따라).
a=$(false)$(echo foo)
를 감시하는 또 다른 경우는 명시 적으로 서브 쉘 : (somecommand)
. 위의 해석에 따르면, 서브 쉘은 0이 아닌 상태를 리턴 할 수 있지만 이것은 상위 쉘에서 간단한 명령이 아니므로 상위 쉘이 계속되어야합니다. 사실, 내가 아는 모든 껍질은이 시점에서 부모가 돌아 오게합니다. 이것은 (cd /some/dir && somecommand)
현재 디렉토리 변경과 같은 작업을 로컬로 유지하기 위해 괄호를 사용하는 경우와 같이 많은 경우에 유용하지만 set -e
, 서브 쉘에서 꺼져 있거나 서브 쉘이 0이 아닌 상태를 리턴하는 방식으로 스펙을 위반합니다. !
실제 명령에서 사용 하는 것과 같이 종료하지 않습니다 . 예를 들어, ash, bash, pdksh, ksh93 및 zsh foo
는 모두 다음 예제에 표시되지 않고 종료됩니다 .
set -e; (set +e; false); echo "This should be displayed"
set -e; (! true); echo "This should be displayed"
그럼에도 불구하고 간단한 명령은 실패하지 않았습니다 set -e
!
세 번째 문제는 사소하지 않은 파이프 라인의 요소입니다 . 실제로 모든 쉘은 마지막 파이프 라인 이외의 파이프 라인 요소의 실패를 무시하고 마지막 파이프 라인 요소와 관련하여 다음 두 가지 동작 중 하나를 나타냅니다.
- 상위 쉘에서 파이프 라인의 마지막 요소를 실행하는 ATT ksh 및 zsh는 평상시처럼 비즈니스를 수행합니다. 파이프 라인의 마지막 요소에서 간단한 명령이 실패하면 해당 명령을 실행하는 쉘이 상위 쉘이됩니다. 종료합니다.
- 다른 셸은 파이프 라인의 마지막 요소가 0이 아닌 상태를 반환하면 종료하여 동작에 근사합니다.
이전과 마찬가지로 set -e
파이프 라인의 마지막 요소에서 부정을 끄 거나 사용하면 쉘을 종료하지 않아야하는 방식으로 0이 아닌 상태를 반환합니다. ATT ksh 및 zsh 이외의 쉘은 종료됩니다.
Bash의 pipefail
옵션을 사용하면 파이프 라인 set -e
의 요소 중 하나가 0이 아닌 상태를 반환하면 파이프 라인이 즉시 종료 됩니다.
추가 합병증으로 bash는 set -e
POSIX 모드가 set -o posix
아니거나 POSIXLY_CORRECT
bash가 시작될 때 환경 에 있지 않는 한 서브 쉘에서 꺼집니다 .
이 모든 것은 POSIX 사양이 불행히도 -e
옵션 을 지정할 때 좋지 않은 작업을 수행한다는 것을 보여줍니다 . 다행히도 기존 쉘은 대부분 동작이 일관됩니다.