programing

명령이 0이 아닌 값을 반환하는 경우 셸 스크립트 중단

bestprogram 2023. 5. 27. 12:01

명령이 0이 아닌 값을 반환하는 경우 셸 스크립트 중단

여러 명령을 호출하는 Bash 셸 스크립트가 있습니다.

명령 중 하나가 0이 아닌 값을 반환하는 경우 반환 값이 1인 셸 스크립트가 자동으로 종료되도록 하고 싶습니다.

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

예를들면,

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

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

스크립트의 시작 부분에 추가합니다.

set -e

이렇게 하면 종료 값이 0이 아닌 단순 명령이 종료되면 셸이 즉시 종료됩니다.단순 명령은 명령의 일부가 아닌 모든 명령입니다.if,while또는until테스트 또는 일부&&또는||목록.

자세한 내용은 "set" 내부 명령의 bash 매뉴얼을 참조하십시오.

중간에 무언가가 실패하고 나머지 스크립트에 대한 가정을 깨뜨렸을 때 스크립트가 완고하게 계속되는 것은 정말 짜증나는 일입니다.저는 개인적으로 거의 모든 휴대용 셸 스크립트를 시작합니다.set -e.

만약 가 bash와 구체적으로 일하고 있다면, 나는 시작할 것입니다.

set -Eeuo pipefail

이는 유사한 방식으로 더 많은 오류 처리를 포함합니다.저는 이것들이 새로운 bash 프로그램에 대한 정상적인 기본값이라고 생각합니다.이러한 옵션의 기능에 대한 자세한 내용은 bash 설명서를 참조하십시오.

승인된 답변에 추가하기

명심하세요set -e가끔은 충분하지 않습니다, 특히 당신이 파이프를 가지고 있다면.

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

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

예상대로 작동하는 경우: 오류configure실행을 중단합니다.

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

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

그리고 이제 그것은 작동하지 않습니다.여기에서는 에 대해 설명하고 해결 방법(배시만 해당)을 제공합니다.

#!/빈/빈세트-eset -o 파이프 실패
./configure | tee configure.log만들다

예제의 if 문은 필요하지 않습니다.이렇게 하면 됩니다.

dosomething1 || exit 1

빌 로리카리의 충고를 받아들여 사용한다면,set -e일부 명령의 경우 다음을 사용해야 할 수 있습니다.

dosomething || true

|| true명령 파이프라인에 다음과 같은 기능을 제공됩니다.true명령이 실패하더라도 반환 값을 반환합니다.-e옵션을 사용하면 스크립트가 중지되지 않습니다.

종료 시 수행해야 할 정리가 있는 경우 유사 신호 ERR과 함께 '트랩'을 사용할 수도 있습니다.이는 INT 또는 다른 신호를 트랩하는 것과 동일한 방식으로 작동합니다. bash는 0이 아닌 값으로 종료되는 명령이 있으면 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 옵션으로 인한 종료 등의 이유로 스크립트가 종료될 때 트랩이 실행됩니다.

$?변수는 거의 필요하지 않습니다. 관용구command; if [ $? -eq 0 ]; then X; fi 항상다같과이써합니다야음합다니▁as▁always로 써야 합니다.if command; then X; fi.

경우에 따라서는$?값과 해야 할 입니다. required는 다음과 같습니다.

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

으로 실행-e또는set -e맨 위에

또한보도 .set -u.

오류가 발생하면 아래 스크립트가 RED 오류 메시지를 인쇄하고 종료합니다.
bash 의 맨 위에 . bash 스크맨 위표시다니합에의트립.

# BASH error handling:
#   exit on command failure
set -e
#   keep track of the last executed command
trap 'LAST_COMMAND=$CURRENT_COMMAND; CURRENT_COMMAND=$BASH_COMMAND' DEBUG
#   on error: print the failed command
trap 'ERROR_CODE=$?; FAILED_COMMAND=$LAST_COMMAND; tput setaf 1; echo "ERROR: command \"$FAILED_COMMAND\" failed with exit code $ERROR_CODE"; put sgr0;' ERR INT TERM

와 같은 표현.

dosomething1 && dosomething2 && dosomething3

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

cat nosuchfile && echo "done"
echo $?
1
#!/bin/bash -e

충분할 겁니다.

Mark Edgars 입력에 대한 추가 질문이 있었기 때문에 참고용으로 다른 질문을 넣었습니다. 여기 전체적인 주제에 대한 추가 예와 터치가 있습니다.

[[ `cmd` ]] && echo success_else_silence

것이 것같은은과 ?cmd || exit errcode누군가가 보여준 바와 같이

예를 들어 다음과 같이 마운트된 경우 파티션이 마운트 해제되었는지 확인합니다.

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

언급URL : https://stackoverflow.com/questions/821396/aborting-a-shell-script-if-any-command-returns-a-non-zero-value