오류 발생 시 Bash 셸 스크립트에서 자동으로 종료
저는 셸 스크립트를 작성하고 있는데 명령 중 하나가 실패할 경우 해당 셸 스크립트의 실행을 중지할 수 있는 기능이 있다면 유용할 것입니다.예는 아래를 참조하십시오.
#!/bin/bash
cd some_dir
./configure --some-flags
make
make install
따라서 이 경우 스크립트가 지정된 디렉토리로 변경할 수 없는 경우 스크립트가 실패하더라도 나중에 ./configure를 수행하지 않을 것입니다.
이제 각 명령에 대해 if 검사를 수행할 수 있다는 것을 잘 알고 있습니다(이것은 가망이 없는 해결책이라고 생각합니다). 하지만 명령 중 하나가 실패할 경우 스크립트를 종료하도록 글로벌 설정이 있습니까?
기본 제공 기능 사용:
#!/bin/bash
set -e
# Any subsequent(*) commands which fail will cause the shell script to exit immediately
또는 통과할 수 있습니다.-e
명령줄에서:
bash -e my_script.sh
다음을 사용하여 이 동작을 사용하지 않도록 설정할 수도 있습니다.set +e
.
당신은 또한 전체 또는 일부를 고용하기를 원할 수 있습니다.-e
-u
-x
그리고.-o pipefail
다음과 같은 옵션:
set -euxo pipefail
-e
오류 발생 시 종료됩니다.-u
정의되지 않은 변수에 대한 오류,-x
실행 전에 명령을 인쇄합니다.-o (for option) pipefail
명령 파이프 오류 시 종료됩니다.일부 gotchas 및 해결 방법은 여기에 잘 문서화되어 있습니다.
(*) 참고:
실패한 명령어가 잠시 후 또는 키워드가 될 때까지 명령어 목록의 일부, if 또는 ellif 예약 단어의 일부, && 또는 || 목록에서 실행된 명령어의 일부, 마지막 && 또는 || 뒤에 이어지는 명령어를 제외한 파이프라인의 모든 명령어의 일부인 경우 셸이 종료되지 않습니다.또는 명령의 반환 값이 !로 반전되는 경우.
(부터)man bash
)
명령 중 하나가 실패하는 즉시 스크립트를 종료하려면 처음에 다음을 추가합니다.
set -e
이로 인해 테스트의 일부가 아닌 명령이 실행되면 스크립트가 즉시 종료됩니다(예:if [ ... ]
조건 또는&&
종료 코드가 0이 아닌 종료 코드를 사용하여 종료합니다.
와 함께 사용합니다.pipefail
.
set -e
set -o pipefail
-e(출구 오류):명령이 0이 아닌 상태로 종료되는 경우 첫 번째 오류 시 스크립트 중단(루프할 때까지 또는 루프할 때, if-tests 및 list constructs 제외)
-o 파이프 고장:파이프라인이 0이 아닌 반환 값을 반환한 파이프의 마지막 명령의 종료 상태를 반환하도록 합니다.
방법은 다음과 같습니다.
#!/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 ***
************
'
첫 번째 줄에 맞는 허용된 답변에 대한 대안:
#!/bin/bash -e
cd some_dir
./configure --some-flags
make
make install
한 가지 관용구는 다음과 같습니다.
cd some_dir && ./configure --some-flags && make && make install
시간이 오래 걸릴 수 있다는 것은 알지만, 더 큰 스크립트의 경우 논리적 기능으로 나눌 수 있습니다.
제 생각에 당신이 찾고 있는 것은trap
명령:
trap command signal [signal ...]
자세한 내용은 이 페이지를 참조하십시오.
다른 옵션은 다음을 사용하는 것입니다.set -e
스크립트의 맨 위에 있는 명령 - 프로그램/명령이 true가 아닌 값을 반환하는 경우 스크립트는 스크립트를 종료합니다.
기존 답변에서 누락된 한 가지 점은 오류 트랩을 상속하는 방법을 보여주는 것입니다. 그bash
은 이러옵한중제하공다니합나를션셸을 사용하는 중 합니다.set
-E
있는 경우, 경모된트랩에 있는
ERR
셸 함수, 명령 대체 및 하위 셸 환경에서 실행되는 명령에 의해 상속됩니다. 그ERR
이러한 경우 트랩은 일반적으로 상속되지 않습니다.
Adam Rosenfield의 사용할 답변 권장 사항set -e
특정한 경우에는 옳지만 잠재적인 함정이 있습니다.GreyCat의 BashFAQ - 105 - set -e(또는 set -orrexit 또는 트랩 ERR)를 참조하십시오.
설명서에 따르면 set -e exit는
단순 명령이 0이 아닌 상태로 종료되는 경우실패한 명령어가 또는 키워드 바로 뒤에 있는 명령어 목록, 의 일부, 또는 목록의 일부이거나, 또는 뒤에 있는 명령어를 제외하고 또는 명령어의 반환 값이 "를 통해 반전된 경우 셸이 종료되지 않습니다.
말은, 말은그은.set -e
다음과 같은 간단한 경우에는 작동하지 않습니다(위키에서 자세한 설명을 찾을 수 있습니다).
연산자 술산 사용자산 사용
let
또는$((..))
(bash
이후)을 4.1로 시킵니다.#!/usr/bin/env bash set -e i=0 let i++ # or ((i++)) on bash 4.1 or later echo "i is $i"
위반 명령이 다음을 통해 실행된 마지막 명령의 일부가 아닌 경우
&&
또는||
를 들어,의 트랩은 되지 않습니다.#!/usr/bin/env bash set -e test -d nosuchdir && echo no dir echo survived
못사경우된에 잘못 되었을 때
if
장문as의 , 종료코드if
문은 마지막으로 실행된 명령의 종료 코드입니다.가 " 아예에서마으로실명같다습니다과음은령된"였습니다.echo
그것은 함정을 발사하지 않을 것이다, 비록.test -d
#!/usr/bin/env bash set -e f() { if test -d nosuchdir; then echo no dir; fi; } f echo survived
와 함께에는 " " " " 를 사용하지 않으면됩니다.
inherit_errexit
는 로설됩다니로 됩니다.bash
4.4#!/usr/bin/env bash set -e foo=$(expr 1-1; true) echo survived
다음과 같이 할당처럼 보이지만 그렇지 않은 명령을 사용하는 경우
export
,declare
,typeset
또는local
은 함호있다습니이출여기수에▁here입니다.f
종료되지 않음local
이전에 설정한 오류 코드를 삭제했습니다.set -e f() { local var=$(somecommand that fails); } g() { local var; var=$(somecommand that fails); }
파이프라인에서 사용되는 경우 위반 명령은 마지막 명령의 일부가 아닙니다.예를 들어, 아래 명령은 계속 수행됩니다.한 가지 옵션은 다음을 활성화입니다.
pipefail
첫 번째 실패한 프로세스의 종료 코드를 반환합니다.set -e somecommand that fails | cat - echo survived
를 사용하지 않는 것이 가장 좋습니다.set -e
오류 검사의 자체 버전을 대신 구현합니다.Bash 스크립트에서 오류 발생에 대한 답변 중 하나에 대한 사용자 지정 오류 처리 구현에 대한 자세한 내용
언급URL : https://stackoverflow.com/questions/2870992/automatic-exit-from-bash-shell-script-on-error
'programing' 카테고리의 다른 글
Excel VBA - 빈 행 삭제 (0) | 2023.06.07 |
---|---|
타입스크립트에 롬복과 같은 것이 있습니까? (0) | 2023.06.07 |
@click 인수를 작업 방법으로 전달하는 방법은 무엇입니까? (0) | 2023.06.07 |
데이터 유형 생략(예: "unsigned int" 대신 "unsigned") (0) | 2023.06.07 |
파이플롯을 사용하여 평활선 그리기 (0) | 2023.06.07 |