어떤 명령이 0이 아닌 값을 반환하면 쉘 스크립트를 중단합니까?


437

많은 명령을 호출하는 Bash 쉘 스크립트가 있습니다. 명령 중 하나가 0이 아닌 값을 반환하면 셸 스크립트가 반환 값 1로 자동 종료되도록하고 싶습니다.

각 명령의 결과를 명시 적으로 확인하지 않고도 가능합니까?

예 :

dosomething1
if [[ $? -ne 0 ]]; then
    exit 1
fi

dosomething2
if [[ $? -ne 0 ]]; then
    exit 1
fi

8
에 추가하여 (또는 ) set -e도 수행하십시오 . 존재하지 않는 변수에 액세스 할 수 있고 진단없이 빈 값을 생성 할 수있는 바보 같은 버그 숨김 동작을 종료합니다. set -uset -eu-u
Kaz

답변:


742

이것을 스크립트의 시작 부분에 추가하십시오 :

set -e

단순 명령이 0이 아닌 종료 값으로 종료되면 쉘이 즉시 종료됩니다. 간단한 명령은 if, while 또는 until test 또는 && 또는 ||의 일부가 아닌 명령입니다. 명부.

자세한 내용은 "set"내부 명령 의 bash (1) 매뉴얼 페이지 를 참조하십시오.

개인적으로 "set -e"로 거의 모든 쉘 스크립트를 시작합니다. 중간에 무언가가 실패하고 스크립트의 나머지 부분에 대한 가정을 깨뜨릴 때 스크립트가 완고하게 계속되는 것은 정말 성가신 일입니다.


36
작동하지만 "/! / usr / bin / env bash"를 사용하고 싶습니다. / bin 이외의 곳에서 bash를 자주 실행하기 때문입니다. 그리고 "#! / usr / bin / env bash -e"는 작동하지 않습니다. 또한 디버깅을 위해 추적 기능을 켜고 싶을 때 "set -xe"를 읽도록 수정하는 것이 좋습니다.
Ville Laurikari

48
또한 스크립트가로 실행되면 shebang 행의 플래그가 무시됩니다 bash script.sh.
Tom Anderson

27
참고 사항 : bash 스크립트 내에서 함수를 선언하는 경우이 기능을 확장하려면 함수가 함수 본문 내에서 -e를 다시 선언해야합니다.
Jin Kim

8
또한 스크립트를 소싱하면 shebang 행은 관련이 없습니다.

4
@JinKim bash 3.2.48에서는 그렇지 않은 것 같습니다. 스크립트 안에서 다음을 시도하십시오 set -e; tf() { false; }; tf; echo 'still here'.. set -e의 본문이 없어도 tf()실행이 중단됩니다. 아마도 당신은 그것이 subshellsset -e의해 상속되지 않았다고 말하고 싶었습니다 .
mklement0

202

허용 된 답변에 추가하려면 :

set -e파이프가있는 경우 특히 충분하지 않다는 것을 명심하십시오 .

예를 들어이 스크립트가 있다고 가정합니다.

#!/bin/bash
set -e 
./configure  > configure.log
make

... 예상대로 작동합니다.에 오류가 발생 configure하면 실행이 중단됩니다.

내일 당신은 겉보기에 사소한 변화를 만듭니다.

#!/bin/bash
set -e 
./configure  | tee configure.log
make

... 지금은 작동하지 않습니다. 이 설명 여기 및 해결 방법 (배쉬 전용) 제공됩니다

#! / bin / bash
세트 -e 
-o pipefail 설정

./configure | 티 configure.log
하다

1
pipefail함께 가야 하는 중요성을 설명해 주셔서 감사합니다 set -o!
Malcolm

83

예제의 if 문은 필요하지 않습니다. 다음과 같이하십시오.

dosomething1 || exit 1

Ville Laurikari의 조언을 받아 set -e다음 명령을 사용하려면 다음을 사용해야합니다.

dosomething || true

|| true명령 파이프 라인은해야 할 것입니다 true하여 있도록 명령이 실패 할 경우에도 반환 값 -e옵션은 스크립트를 죽이지 않을 것이다.


1
나는 이것을 좋아한다. 특히 최고의 대답은 bash 중심이기 때문에 (zsh 스크립팅에 적용되는지 여부에 대해서는 명확하지 않습니다). 그리고 나는 그것을 찾을 수 있지만, 당신의 논리는 분명하기 때문에 더 명확합니다.
g33kz0r 2016 년

set -ebash 중심이 아닙니다-원래 Bourne Shell에서도 지원됩니다.
Marcos Vives Del Sol

27

종료시 정리가 필요한 경우 의사 신호 ERR과 함께 '트랩'을 사용할 수도 있습니다. 이것은 INT 또는 다른 신호를 포착하는 것과 같은 방식으로 작동합니다. 명령이 0이 아닌 값으로 종료되면 bash에서 ERR이 발생합니다.

# Create the trap with   
#    trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah

또는 특히 "set -e"를 사용하는 경우 EXIT를 트랩 할 수 있습니다. 그러면 스크립트가 정상적인 종료, 인터럽트, -e 옵션으로 인한 종료 등 어떤 이유로 종료 될 때 트랩이 실행됩니다.


12

$?변수가 거의 필요하지 않습니다. 의사 관용구 command; if [ $? -eq 0 ]; then X; fi는 항상로 작성해야합니다 if command; then X; fi.

$?필요한 경우 는 여러 값에 대해 점검해야하는 경우입니다.

command
case $? in
  (0) X;;
  (1) Y;;
  (2) Z;;
esac

또는 $?재사용하거나 달리 조작해야 할 경우 :

if command; then
  echo "command successful" >&2
else
  ret=$?
  echo "command failed with exit code $ret" >&2
  exit $ret
fi

3
왜 "항상 기록해야"합니까? 내 말은 왜 "그렇게" 해야 합니까? 명령이 길면 (여러 가지 옵션으로 GCC를 호출한다고 생각하면) 리턴 상태를 확인하기 전에 명령을 실행하는 것이 훨씬 더 읽기 쉽습니다.
ysap

명령이 너무 길면 이름을 지정하여 분리 할 수 ​​있습니다 (쉘 기능 정의).
Mark Edgar

12

상단 -e또는 set -e상단에서 실행하십시오 .

또한보십시오 set -u.


34
잠재적으로 다른 사람을 구하기 위해 읽을 필요성 help set: -u설정되지 않은 변수에 대한 참조를 오류로 처리합니다.
mklement0

1
그래서 하나의 set -u또는 set -e둘 다하지? @lumpynose
ericn

1
@eric 몇 년 전에 은퇴했습니다. 나는 내 일을 좋아했지만 나이 든 뇌는 모든 것을 잊어 버렸습니다. 나는 당신이 둘 다를 함께 사용할 수 있다고 생각합니다. 내 말은 나쁜 표현이다. 나는 "그리고 / 또는"라고 말 했어야했다.
lumpynose

3

같은 표현

dosomething1 && dosomething2 && dosomething3

명령 중 하나가 0이 아닌 값으로 리턴되면 처리가 중지됩니다. 예를 들어 다음 명령은 "완료"를 인쇄하지 않습니다.

cat nosuchfile && echo "done"
echo $?
1


-2

Mark Edgars 입력에 대한 추가 질문이 있었고 여기에 추가 예제가 있으며 전반적인 주제에 대해 설명하기 때문에 참조를 위해 다른 질문을 던졌습니다.

[[ `cmd` ]] && echo success_else_silence

그것은 cmd || exit errcode누군가가 보여준 것과 같습니다 .

예. 마운트 된 경우 파티션이 마운트 해제되었는지 확인하고 싶습니다.

[[ `mount | grep /dev/sda1` ]] && umount /dev/sda1 

5
아니요, [[ cmd`]]`는 같은 것이 아닙니다. 명령의 출력 상태가 비어 있으면 명령의 출력이 비어 있으면 false이고 그렇지 않으면 true입니다.
Gilles 'SO- 악마 그만'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.