다음 스니펫을 고려해보세요.
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 -E
ERR
이와 같은 개선된 버전은 트랩 과 결합되어 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