오류 발생시 bash 쉘 스크립트에서 자동 종료
몇 가지 셸 스크립트를 작성 중이며 명령 중 하나라도 실패하면 해당 셸 스크립트의 실행을 중지 할 수있는 기능이 있으면 유용합니다. 예는 아래를 참조하십시오.
#!/bin/bash
cd some_dir
./configure --some-flags
make
make install
따라서이 경우 스크립트가 표시된 디렉토리로 변경할 수없는 경우 실패하면 나중에 ./configure를 수행하고 싶지 않을 것입니다.
이제 각 명령에 대해 if 검사를 할 수 있다는 것을 잘 알고 있습니다 (절망적 인 해결책이라고 생각합니다).하지만 명령 중 하나가 실패 할 경우 스크립트를 종료하는 전역 설정이 있습니까?
set -e
내장 사용 :
#!/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
정의되지 않은 변수 오류 및 -o (for option) pipefail
명령 파이프 실패시 종료됩니다. 일부 문제와 해결 방법은 여기에 잘 설명되어 있습니다 .
(*) 노트:
실패한 명령이 while 또는 until 키워드 바로 뒤에 오는 명령 목록의 일부, if 또는 elif 예약어 다음에 오는 테스트의 일부, && 또는 || 에서 실행되는 명령의 일부인 경우 쉘은 종료 되지 않습니다. 마지막 && 또는 || 다음에 오는 명령을 제외한 목록 , 파이프 라인에 있지만 마지막 명령이거나 명령의 반환 값이 !
(부터 man bash
)
명령 중 하나가 실패하자마자 스크립트를 종료하려면 처음에 다음을 추가하십시오.
set -e
이로 인해 일부 테스트의 일부가 아닌 일부 명령 (예 : if [ ... ]
조건 또는 &&
구성)이 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 ***
************
'
와 함께 사용하십시오 pipefail
.
set -e
set -o pipefail
-e (errexit) : 명령이 0이 아닌 상태로 종료 될 때 첫 번째 오류시 스크립트 중단 (until 또는 while 루프, if-tests, 목록 구성 제외)
-o pipefail : 파이프 라인이 0이 아닌 반환 값을 반환 한 파이프에서 마지막 명령의 종료 상태를 반환하도록합니다.
첫 번째 줄에 맞는 수락 된 답변의 대안 :
#!/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 ...]
For more information, see this page.
Another option is to use the set -e
command at the top of your script - it will make the script exit if any program / command returns a non true value.
One point missed in the existing answers is show how to inherit the error traps. The bash
shell provides one such option for that using set
-E
If set, any trap on
ERR
is inherited by shell functions, command substitutions, and commands executed in a subshell environment. TheERR
trap is normally not inherited in such cases.
Adam Rosenfield's answer recommendation to use set -e
is right in certain cases but it has its own potential pitfalls. See GreyCat's BashFAQ - 105 - Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?
According to the manual, set -e exits
if a simple commandexits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a
while
oruntil
keyword, part of thetest in a if statement
, part of an&&
or||
list except the command following thefinal && or ||
,any command in a pipeline but the last
, or if the command's return value is being inverted via!
".
which means, set -e
does not work under the following simple cases (detailed explanations can be found on the wiki)
Using the arithmetic operator
let
or$((..))
(bash
4.1 onwards) to increment a variable value as#!/usr/bin/env bash set -e i=0 let i++ # or ((i++)) on bash 4.1 or later echo "i is $i"
If the offending command is not part of the last command executed via
&&
or||
. For e.g. the below trap wouldn't fire when its expected to#!/usr/bin/env bash set -e test -d nosuchdir && echo no dir echo survived
When used incorrectly in an
if
statement as, the exit code of theif
statement is the exit code of the last executed command. In the example below the last executed command wasecho
which wouldn't fire the trap, even though thetest -d
failed#!/usr/bin/env bash set -e f() { if test -d nosuchdir; then echo no dir; fi; } f echo survived
When used with command-substitution, they are ignored, unless
inherit_errexit
is set withbash
4.4#!/usr/bin/env bash set -e foo=$(expr 1-1; true) echo survived
when you use commands that look like assignments but aren't, such as
export
,declare
,typeset
orlocal
. Here the function call tof
will not exit aslocal
has swept the error code that was set previously.set -e f() { local var=$(somecommand that fails); } g() { local var; var=$(somecommand that fails); }
When used in a pipeline, and the offending command is not part of the last command. For e.g. the below command would still go through. One options is to enable
pipefail
by returning the exit code of the first failed process:set -e somecommand that fails | cat - echo survived
The ideal recommendation is to not use set -e
and implement an own version of error checking instead. More information on implementing custom error handling on one of my answers to Raise error in a Bash script
참고URL : https://stackoverflow.com/questions/2870992/automatic-exit-from-bash-shell-script-on-error
'Programing' 카테고리의 다른 글
클라이언트가 JavaScript 파일을 새로 고치도록하려면 어떻게해야합니까? (0) | 2020.10.04 |
---|---|
내가 사용하십니까 (0) | 2020.10.04 |
Python에서 이달의 마지막 날 가져 오기 (0) | 2020.10.04 |
Scala에서 객체와 클래스의 차이점 (0) | 2020.10.03 |
모든 Unix 그룹 이름을 나열하는 명령이 있습니까? (0) | 2020.10.03 |