서브쉘에서 쉘 스크립트 종료

서브쉘에서 쉘 스크립트 종료

다음 스니펫을 고려해보세요.

stop () {
    echo "${1}" 1>&2
    exit 1
}

func () {
    if false; then
        echo "foo"
    else
        stop "something went wrong"
    fi
}

일반적으로 호출되면 func스크립트가 종료되며 이는 예상되는 동작입니다. 그러나 서브셸에서 실행되는 경우에는 다음과 같습니다.

result=`func`

스크립트를 종료하지 않습니다. 이는 호출 코드가 매번 함수의 종료 상태를 확인해야 함을 의미합니다. 이것을 피할 수 있는 방법이 있나요? 이것이 set -e목적인가요?

답변1

예를 들어 종료 상태 77을 설정하여 모든 수준의 하위 쉘을 종료한 다음 실행할 수 있습니다.

set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR

(
  echo here
  (
    echo there
    (
      exit 12 # not 77, exit only this subshell
    )
    echo ici
    exit 77 # exit all subshells
  )
  echo not here
)
echo not here either

set -EERR이와 같은 개선된 버전은 트랩 과 결합되어 set -e사용자가 자신의 오류 처리를 정의할 수 있게 해줍니다.

zsh에서는 ERR 트랩이 자동으로 상속되므로 그럴 필요가 없습니다 . 또한 트랩을 함수로 정의하고 다음과 같이 수정할 set -E수도 있습니다 .TRAPERR()$functions[TRAPERR]functions[TRAPERR]="echo was here; $functions[TRAPERR]"

답변2

할 수 있다kill $$()를 호출하기 전에 원래 쉘을 종료하면 exit작동할 수 있습니다. 하지만:

  • 내 생각엔 못생긴 것 같아
  • 두 번째 서브쉘이 있는 경우, 즉 서브쉘 내의 서브쉘을 사용하면 손상됩니다.

대신 다음 중 하나를 사용할 수 있습니다.Bash FAQ에서 값을 반환하는 여러 가지 방법. 불행히도 대부분은 그다지 좋지 않습니다. 각 함수 호출 후에 오류를 확인할 수도 있습니다(-e질문이 많아요). 이렇게 하거나 대신 Perl을 사용하십시오.

답변3

대안으로 중첩된 하위 쉘(모든 호출자와 작업자 프로세스가 신호를 수신함)에서 작동하는 것을 kill $$시도해 볼 수도 있지만 ... 여전히 잔인하고 보기 흉합니다.kill 0

답변4

한 줄로 된 내 이탈의 예:

COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit

관련 정보