for 루프의 결과에 따라 이 스크립트를 오류 종료하도록 하려면 어떻게 해야 합니까?

for 루프의 결과에 따라 이 스크립트를 오류 종료하도록 하려면 어떻게 해야 합니까?

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

루프 를 추가했습니다 for.

  1. 몇 초 동안 일시 중지한 후 curl명령 을 다시 시도하세요.
  2. for 루프의 맨 아래에서 0이 아닌 기본 종료 상태를 정의하는 데 사용합니다 false. - 컬 명령이 성공하면 루프가 중단되고 마지막 명령의 종료 상태는 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이 아닌 종료 코드로 종료되면 코드가 종료됩니다 .

퀴즈의 요점으로 1in은 exit 1필요하지 않습니다. 다운로드가 실패하면 일반 exit명령은 마지막으로 실행된 명령의 종료 상태(코드=1)로 종료됩니다 . false다운로드가 성공하면 루프의 종료 코드는 echo명령의 종료 코드입니다. echo일반적으로 code=0으로 종료되며 이는 성공을 의미합니다. 이 경우에는 ||트리거되지 않으며 exit명령이 실행되지 않습니다.

마지막으로, set -o errexit놀라움으로 가득 차 있을 수 있다는 점에 유의하세요. 장점과 단점에 대한 논의는 다음을 참조하세요.그렉의 FAQ #105.

선적 서류 비치

에서 man bash:

~을 위한(( expr1 ; expr2 ; expr3 )) ;하다목록 ; 완료
먼저, 산술 표현식 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.

작성된 예제 스크립트는 errexit가 설정된 경우 curl처음 호출할 때 첫 번째 명령 실패 후 종료되어야 합니다.false

-e어떻게 작동하는지 확인하기 위해(저는 set에 대한 약칭을 사용합니다 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

관련 정보