[unix] for 루프의 결과에 따라이 스크립트를 오류 엑시트로 만들려면 어떻게해야합니까?

set -o errexit오류가 발생하면 전체 스크립트가 실패 시점에 종료되도록 사용하는 bash 스크립트 가 있습니다.
스크립트는 curl의도 한 파일을 검색하지 못하는 명령을 실행 하지만,이 경우 스크립트는 오류 종료에 실패하지 않습니다.

for루프를 추가했습니다

  1. 몇 초 동안 일시 중지 한 후 curl명령 을 다시 시도하십시오.
  2. 사용 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이 아닌 종료 코드로 종료되면 코드가 종료됩니다 .

사소한 점으로 1in 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


답변