배경

배경

배경

bash 3, 4, 5에서 각각 다음 코드를 실행하면 다른 결과가 나타납니다.

(function handle_error () { echo ERROR; }; trap handle_error ERR; (exit 1))

(exit 1)호출한 명령이 실패할 수 있다고 상상해 보십시오 . 이 경우 항상 실패하지만 그것은 중요하지 않습니다. handle_error0이 아닌 종료 코드로 종료될 때 호출되기를 원합니다 . 매뉴얼에 따르면, 이것이 정확히 trap handle_error ERR해야 할 일입니다.

질문

bash 버전 3을 사용하는 로컬 시스템과 완전히 다른 운영 체제에 bash 버전 4를 사용하는 원격 시스템이 있습니다.

  • bash 3.2.57(1), 3.2.48(1): 출력을 반환하지 않습니다. man bash내장 에서 발췌 trap:

    sigspec이 ERR인 경우 단순 명령의 종료 상태가 0이 아닐 때마다 다음 조건에 따라 arg 명령이 실행됩니다.

  • bash 4.4.23(1), 4.4.12(1): ERROR예상대로 인쇄됩니다. man bash내장 에서 발췌 trap:

    sigspec이 ERR인 경우 파이프라인(단일 단순 명령으로 구성될 수 있음), 목록 또는 복합 명령이 0이 아닌 종료 상태를 반환할 때마다 다음 조건에 따라 arg 명령이 실행됩니다.

  • bash 5.0.2(1): ERROR예상대로 인쇄됩니다.

문서를 보면 두 버전이 모두 동일하게 작동해야 한다고 생각하지만 그렇지 않습니다.

Freenode 에 로그인하여 이 동작이 모든 주요 버전 3, 4, 5에서 동일하다는 것을 확인했습니다. 단 , 주요 버전을 지정할 수 있는 #bash셸 봇(닉네임)이 다릅니다 . shbot이 셸 봇은 제가 시도한 두 시스템과 다른 운영 체제에서 실행되고 있으며, 제가 액세스할 수 있는 동일한 bash 주 버전과 비교했을 때 부 버전도 다릅니다.

질문

누군가 bash 버전 3, 4, 5에서 이 동작이 다른 이유를 설명하는 신뢰할 수 있는 소스를 지적할 수 있습니까? 나는 이것이 실수라고 믿기 어렵다. 그리워지는 이유가 또 있을 것 같아요.

답변1

이것은 Bash 3.2의 버그처럼 보입니다.

항목을 찾을 수 없습니다.변경 로그이것은 직접 일치합니다. POSIX 합의( bash-4.0-rc1에서 bash-4.0-release로 변경되는 프로젝트) errexit와 일치하도록 옵션 동작을 변경하는 것에 대한 모호한 언급만 있습니다 .l

비슷한 질문이 있으므로 이것은 관련이 있을 수 있습니다. errexitBash 3.2에서는 트리거되지 않지만 Bash 4.0에서는 트리거됩니다(하위 쉘 명령이 실패하면 쉘이 종료되어야 하기 때문에 아무것도 인쇄하지 않아야 합니다).

$ ./bash3.2 -c 'set -e; (exit 1); echo end.'
end.

여기서 문제는 서브쉘인 것 같습니다. 이는 두 버전 모두에서 작동합니다.

$ ./bash3.2 -c 'trap "echo ERROR" ERR; false'
ERROR

관련 정보