set -o errexit
오류가 발생하면 전체 스크립트가 종료되도록 사용하는 bash 스크립트가 있습니다 .
스크립트는 curl
때때로 예상된 파일을 검색하지 못하는 명령을 실행합니다. 그러나 이런 일이 발생하면 스크립트가 오류와 함께 종료되지 않습니다.
for
루프 를 추가했습니다
- 몇 초 동안 일시 중지하고
curl
명령 을 다시 시도하십시오. - for 루프의 맨 아래에서
false
0이 아닌 기본 종료 상태를 정의하는 데 사용합니다. 컬 명령이 성공하면 루프가 중단되고 마지막 명령의 종료 상태는 0이 되어야 합니다.
#! /bin/bash
set -o errexit
# ...
for (( i=1; i<5; i++ ))
do
echo "attempt number: "$i
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
if [ -f ~/.vim/autoload/pathogen.vim ]
then
echo "file has been retrieved by curl, so breaking now..."
break;
fi
echo "curl'ed file doesn't yet exist, so now will wait 5 seconds and retry"
sleep 5
# exit with non-zero status so main script will errexit
false
done
# rest of script .....
문제는 curl
명령이 실패하면 루프가 명령을 5번 다시 시도한다는 것입니다. 모든 시도가 실패하면 for 루프가 종료되고 기본 스크립트가 다시 시작됩니다 errexit
.
이 명령문이 실패하면 전체 스크립트를 종료하려면 어떻게 해야 합니까 curl
?
답변1
바꾸다:
done
그리고:
done || exit 1
for
이로 인해 루프가 0이 아닌 종료 코드로 종료되면 코드가 종료됩니다.
그런데 1
in은 필요하지 않습니다. 다운로드가 실패하면 exit 1
일반 exit
명령은 마지막으로 실행된 명령의 종료 상태(코드=1)로 종료됩니다. false
다운로드가 성공하면 루프의 종료 코드는 echo
명령의 종료 코드입니다. echo
일반적으로 성공을 나타내는 code=0으로 종료됩니다. 이 경우 ||
아무 것도 트리거되지 않으며 exit
명령이 실행되지 않습니다.
set -o errexit
마지막으로, 이 내용은 놀라움으로 가득 차 있을 수 있다는 점에 유의하세요 . 장점과 단점에 대한 논의는 다음을 참조하세요.그렉의 FAQ #105.
문서
에서 man bash
:
~을 위한((식1;식2;식3));하다목록 ; 완벽한
먼저, 산술 표현식 expr1은 아래 산술 평가에서 설명한 규칙에 따라 평가됩니다. 그런 다음 산술 표현식 expr2는 0으로 평가될 때까지 반복적으로 평가됩니다. expr2가 0이 아닌 값으로 평가될 때마다 list가 실행되고 산술 표현식 expr3이 평가됩니다. 표현식이 생략되면 1로 평가됩니다. 반환 값은 목록에서 실행된 마지막 명령의 종료 상태이거나, 표현식이 유효하지 않은 경우 false입니다.[강조 추가]
답변2
첫 번째 실패 시 루프를 중지하고 이를 방지하려면 set -e
다음을 수행할 수 있습니다.
for i in `seq 1 10`; do
run_command || exit 1;
done
답변3
이를 설정 한 경우 errexit
이 false
명령문으로 인해 스크립트가 즉시 종료됩니다. curl
명령이 실패 해도 마찬가지입니다.
작성된 예제 스크립트는 curl
errexit가 설정된 경우 첫 번째 명령이 실패한 후 첫 번째 호출에서 종료되어야 합니다.false
어떻게 작동하는지 확인하려면(저는 단축형을 사용하여 -e
설정했습니다 errexit
.
$ ( set -e; false; echo still here )
$
$ ( set +e; false; echo still here )
still here
$
따라서 curl
명령이 여러 번 실행되면 스크립트에 errexit
설정이 없습니다.
답변4
set -o errexit
프로세스에서 돌아와야 하기 때문에 루프와 서브셸에서는 까다로울 수 있습니다.
루프를 끊는 것은(정상 작동 중에도) 나쁜 습관으로 간주됩니다. 나를 구식이라고 부르면 두 가지 조건에 대해 for 루프보다 while 루프를 사용하는 것을 선호할 수 있지만 다음을 읽는 것이 더 좋습니다.
i=1
RET=-1
while [ $i -le 5 ] && [ $RET -ne 0 ]; do
[ $i -eq 1 ] || sleep 5
echo "attempt number: "$i
curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
RET=$?
i=$((i+1))
done
exit $RET