set -o errexit
오류가 발생하면 전체 스크립트가 실패 시점에 종료되도록 사용하는 bash 스크립트 가 있습니다.
스크립트는 curl
의도 한 파일을 검색하지 못하는 명령을 실행 하지만,이 경우 스크립트는 오류 종료에 실패하지 않습니다.
for
루프를 추가했습니다
- 몇 초 동안 일시 중지 한 후
curl
명령 을 다시 시도하십시오. - 사용
false
기본 0이 아닌 종료 상태를 정의하는 for 루프의 맨 아래에 – 컬 명령이 성공하면 – 루프 휴식과 마지막 명령의 종료 상태를 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
명령이 실패 할 때 루프가 명령을 다섯 번 재 시도하는 것입니다. 모든 시도가 실패하면 for 루프가 완료되고 기본 스크립트가 재개됩니다 errexit
.
이 curl
문이 실패하면 전체 스크립트를 종료하려면 어떻게해야합니까?
답변
바꾸다:
done
와:
done || exit 1
for
루프가 0이 아닌 종료 코드로 종료되면 코드가 종료됩니다 .
사소한 점으로 1
in exit 1
은 필요하지 않습니다. 일반 exit
명령은 false
다운로드에 실패하면 마지막으로 실행 된 명령의 종료 상태 ((코드 = 1))로 종료됩니다. 다운로드가 성공하면 루프의 종료 코드는 echo
명령 의 종료 코드입니다 . echo
일반적으로 code = 0으로 종료합니다. 이 경우 ||
에는 트리거되지 않으며 exit
명령이 실행되지 않습니다.
마지막으로 set -o errexit
놀라움으로 가득 차 있습니다. 장단점에 대한 논의는 Greg의 FAQ # 105를 참조하십시오 .
선적 서류 비치
보낸 사람 man bash
:
for ((expr1; expr2; expr3)); 할 목록을;
완료
먼저 산술 표현식은 expr1 규칙 산술 EVALUATION 아래 설명에 따라 평가된다. 그런 다음 산술 표현식 expr2는 0으로 평가 될 때까지 반복적으로 평가됩니다. expr2가 0이 아닌 값으로 평가 될 때마다 목록이 실행되고 산술 표현식 expr3이 평가됩니다. 표현식이 생략되면 1로 평가되는 것처럼 작동합니다.
리턴 값은 실행 된 list에서 마지막 명령의 종료 상태이거나 표현식이 유효하지 않은 경우 false입니다. [엠파 시스 추가]
답변
당신이 경우 errexit
설정, 다음 false
문은 즉시 종료에 스크립트를 야기한다. curl
명령이 실패한 경우에도 마찬가지입니다.
errexit가 설정된 경우 curl
처음 호출 false
할 때 첫 번째 명령이 실패한 후 작성된 스크립트의 예제 스크립트 입니다.
작동 방식을 확인하려면 (약칭 -e
을 사용하여 설정하십시오 errexit
.
$ ( set -e; false; echo still here )
$
$ ( set +e; false; echo still here )
still here
$
따라서 curl
명령이 두 번 이상 실행되면이 스크립트가 errexit
설정 되지 않은 것 입니다.
답변
set -o errexit
프로세스에서 빠져 나가야하기 때문에 루프와 서브 쉘에서 까다로울 수 있습니다.
루프를 끊는 것은 (정상적인 작동 중에도) 나쁜 습관으로 간주됩니다. 두 가지 조건에서 for-loop보다는 while-loop를 선호하도록 old-school을 호출 할 수는 있지만 읽는 것이 더 좋습니다.
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
답변
경우는 errexit
설정하고있다 curl
명령은 바로 실패 컬 명령 후 스크립트 종료를 실패합니다. bash 매뉴얼에는 set -e
복합 명령에서 단일의 실패한 리턴 상태 를 무시하는 힌트가 없습니다 . 복합 명령 set -e
이 무시 되는 컨텍스트에서 실행되는 경우에만 해당됩니다 .
https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin
RobertL이 게시 한 약간 수정 된 예제를 사용해보십시오. 이것은 false 명령 바로 다음의 첫 번째 반복에서 중지됩니다.
( set -e; for (( i=1; i<5; i++ )); do echo $i; false; echo "${i}. iteration done"; done ; echo "loop done" )
답변
curl 명령에 –fail 옵션을 추가하면 문제가 해결되며, curl 명령이 실패하면 스크립트가 실패하고 오류가 발생하면 jenkins pipeline에서 curl을 사용할 때 매우 유용합니다.
curl -LSso --fail ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim