상속_errexit가 작동하지 않는 경우는 언제인가요?

상속_errexit가 작동하지 않는 경우는 언제인가요?
#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
a=$(cat no-such-file)
echo survived
$ /tmp/a.sh
cat: no-such-file: No such file or directory
#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
echo -n $(cat no-such-file)
echo survived
$ /tmp/a.sh
cat: no-such-file: No such file or directory
survived
#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
f() { :; }
f $(cat no-such-file)
echo survived
$ /tmp/a.sh
cat: no-such-file: No such file or directory
survived

다른 경우는 없나요? 아니면 일부 일반화?

답변1

TL, DR: 의 이점을 얻으려면 set -e명령 대체 결과를 변수에 직접 할당하십시오(선택적으로 주변에 추가 문자열 포함). 여러 명령 대체를 함께 결합하거나 명령 인수에 명령 대체를 사용하지 마십시오.

문제는 에 있지 않습니다 inherit_errexit. 작동 중입니다. 문제는 set -ebash에만 국한되지 않는 제한 사항입니다. 다른 sh와 유사한 쉘에도 동일한 문제가 있습니다.

데모: 두 번째 예제의 변형을 실행하세요.

$ cat b2.sh 
#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
echo -n $(cat no-such-file; echo >&2 after cat)
echo survived
$ ./b2.sh 
cat: no-such-file: No such file or directory
survived

실행되지 않았 음을 참고하세요 echo >&2 after cat. 꺼져 있었다면 그랬을 것이다 inherit_errexit.

문제는 set -e간단한 경우에만 오류 발생 시 실행을 중지한다는 것입니다. 명령 대체가 실패 상태를 반환하는 경우 대체가 포함된 단순 명령의 실행이 중지되지 않습니다. 기껏해야 단순 명령의 반환 상태를 설정하여 스크립트 실행을 중지할 수 있습니다. "간단한 명령"은 할당, 리디렉션 및 선택적 실행 가능 명령 이름과 인수로 구성됩니다. 리디렉션이 실패하면 반환 상태는 1입니다. 그렇지 않고 명령 이름이 있는 경우 단순 명령의 반환 상태는 실행 가능한 명령의 반환 상태입니다. 그렇지 않으면 반환 상태는 마지막 명령 대체의 반환 상태이거나 반환 상태가 없으면 0입니다. 다음은 간단한 명령의 몇 가지 예입니다.

  • true </no/such/file→ 리디렉션 실패로 인해 상태 1
  • false </dev/null→ 상태 1부터false
  • a=b→ 고장날 수 있는 부분이 없어 상태 0
  • a=$(exit 0) b=$(exit 1) c=$(exit 2)→ 마지막 명령 대체의 상태 2
  • a=$(exit 2) b=$(exit 1) c=$(exit 0)→ 마지막 명령 대체에서 상태 0
  • true $(exit 0) $(exit 1) $(exit 2)→ 상태 0부터true

다시 한 번 말하지만, 모든 경우에 set -e명령 상태가 0이 아닌 경우에만 스크립트가 중지됩니다. 포함된 명령의 상태는 직접적인 관련이 없습니다.

따라서 두 번째 스크립트에서는 명령 대체 내부에서 어떤 일이 발생하는지에 관계없이 echo -n $(…)상태가 0입니다 echo(쓰기에 실패한 경우 제외 ). echo따라서 스크립트가 활성화되어 있어도 여기서 멈추지 않습니다 set -e. 마찬가지로 세 번째 스크립트에서는 f $(…)상태가 0 from 입니다 f.

관련 정보