오류 발생시 스크립트 종료


141

다음 if과 같은 기능 을 가진 쉘 스크립트를 작성 중입니다.

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

오류 메시지가 표시된 후 스크립트 실행이 완료되기를 원합니다. 어떻게해야합니까?

답변:


137

찾고 exit있습니까?

이것은 가장 좋은 배쉬 가이드입니다. http://tldp.org/LDP/abs/html/

문맥:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
    exit 1 # terminate and indicate error
fi

...


그 배쉬 링크는 굉장하다! BashFAQ는 BashRecipes로 배치하는 것이 좋습니다.
Pete Alvin

337

set -e스크립트 를 넣으면 스크립트는 명령이 실패하자마자 (즉, 명령이 0이 아닌 상태를 반환하는 즉시) 종료됩니다. 이것은 당신이 당신의 자신의 메시지를 쓸 수 없지만 종종 실패한 명령의 자신의 메시지로 충분합니다.

이 방법의 장점은 자동이라는 것입니다. 오류 사례를 잊어 버릴 위험이 없습니다.

그 상태 (예 : 조건에 따라 시험 할 때, 명령 if, &&또는 ||) 스크립트를 종료하지 않습니다는 (다른 조건은 무의미). 실패가 중요하지 않은 간헐적 인 명령에 대한 관용구는 command-that-may-fail || true입니다. set -e을 사용하여 스크립트의 일부를 끌 수도 있습니다 set +e.


3
mywiki.wooledge.org/BashFAQ/105 에 따르면 ,이 기능은 어떤 명령의 오류 코드가 자동 종료를 유발 하는지를 결정하는 데있어 애매 모호하고 복잡한 역사를 가지고 있습니다. 또한 "Bash가이 '기능'에 대해 매우 미끄러운 POSIX 정의를 추적하려고 시도함에 따라 규칙이 한 Bash 버전에서 다른 Bash 버전으로 변경됩니다." @Dennis Williamson과 stackoverflow.com/questions/19622198/…에 대한 답변에 동의합니다 . 트랩 'error_handler'ERR을 사용하십시오. 함정이라도!
Bondolin

3
종종 -x플래그와 함께 플래그를 사용하면 -e프로그램이 종료되는 위치를 추적하는 것으로 충분합니다. 이는 스크립트 사용자가 개발자이기도 함을 의미합니다.
Alex

좋지만 OP는 자체 정의 예외에서 스크립트를 종료해야한다고 생각합니다.
vdegenne

42

당신이 맹목적으로 종료 대신 사용하는 대신 오류를 처리 할 수 있도록하려면 set -e,를 사용 trap상의 ERR의사 신호.

#!/bin/bash
f () {
    errorCode=$? # save the exit code as the first thing done in the trap function
    echo "error $errorCode"
    echo "the command executing at the time of the error was"
    echo "$BASH_COMMAND"
    echo "on line ${BASH_LINENO[0]}"
    # do some error handling, cleanup, logging, notification
    # $BASH_COMMAND contains the command that was being executed at the time of the trap
    # ${BASH_LINENO[0]} contains the line number in the script of that command
    # exit the script or return to try again, etc.
    exit $errorCode  # or use some other value or do return instead
}
trap f ERR
# do some stuff
false # returns 1 so it triggers the trap
# maybe do some other stuff

다른 트랩은 일반적인 유닉스 신호 플러스 다른 배쉬 의사 신호를 포함하여 다른 신호를 처리하도록 설정할 수 있습니다 RETURNDEBUG.


8

방법은 다음과 같습니다.

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'

stderr에게 왜 완료 메시지가 표시됩니까?
MattBianco

1
이것은 일반적인 관행이므로 스크립트 출력을 표준 출력으로 파이프하여 다른 프로세스가 정보 메시지를 중간에 갖지 않고도 얻을 수 있습니다.
supercobra 2016 년

2
stderr의 모든 것을 문제의 표시로 처리하는 것이 일반적으로 일반적입니다.
MattBianco

1
과거에는 'set -e'가 항상 효과가 있었지만 오늘 밤에는 Alpine Linux Docker 이미지에서 아무런 영향을 미치지 않는 상황을 겪었습니다. 매우 감사.
신시사이저

@supercobra 일반적인 관행? 어디?
Thorbjørn Ravn Andersen

-8

exit 1당신이 필요한 전부입니다. 은 1당신이 원하는 경우에, 말, 변경할 수 있도록 반환 코드 1성공적인 실행을 의미하고 -1그런 오류 또는 무언가를 의미 할 수 있습니다.


13
유닉스에서의 성공은 항상 사용할 때 도움이 될 수 0입니다 test또는 &&||.
mouviciel

5
쉘 스크립트에서 mouviciel의 의견을 확장하면 0은 항상 성공을 의미하고 1에서 255는 실패를 의미합니다. -1이 범위를 벗어났습니다 (종종 255와 동일한 효과가 있으므로 실패는 1과 같습니다).
Gilles 'SO- 악마 중지'12

@mouviciel, @Gilles : 추가 정보 감사합니다. 내가 bash를 처리 한 지 오래되었습니다.
DGH December

이것은 리턴 코드 사용법의 나쁜 예입니다. 그렇지 않으면 훌륭한 답변이 될 것입니다.
Brad Koch

1
성공을 위해 1을 잘못 권장하는 것 외에도 -1을 사용할 수 없습니다 (종료 코드는 서명되지 않음).
tripleee
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.