404 오류가 발생한 후 'wget'을 어떻게 중지합니까?

404 오류가 발생한 후 'wget'을 어떻게 중지합니까?

다음과 함께 중괄호 확장을 사용하면 wget순차적으로 번호가 매겨진 이미지를 쉽게 얻을 수 있습니다 .

$ wget 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'

번호 가 매겨진 처음 10개의 90.jpg파일을 가져온 99.jpg다음100.jpg404: 파일을 찾을 수 없습니다오류(내 서버에는 이미지가 100개만 저장되어 있습니다.) 예를 들어 더 큰 범위를 사용 {00..200}하고 100개의 존재하지 않는 파일이 있는 경우 이러한 존재하지 않는 파일은 더 큰 "문제"가 되어 스크립트의 실행 시간을 늘리고 서버에 약간의 부담이 될 수도 있습니다. 최소한 문제는 있습니다).

wget처음 404 오류가 발생한 후 중지 할 수 있는 방법이 있습니까 ? (또는 다른 이유로 인해 파일이 범위 내에서 손실되는 경우 연속으로 두 개가 더 좋습니다.) 대답에는 중괄호 확장을 사용할 필요가 없습니다.

답변1

루프에 만족한다면:

for url in 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'
do
    wget "$url" || break
done

wget이는 실패할 때까지 확장의 모든 URL에 대해 실행된 다음 break루프를 종료합니다.

연속으로 두 번의 실패가 예상되면 상황이 더 복잡해집니다.

for url in 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'
do
    if wget "$url"
    then
        failed=
    elif [ "$failed" ]
    then
        break
    else
        failed=yes
    fi
done

&&사용하고 ||약간 축소할 수는 있지만 if정말 보기 흉해집니다.

wget나는 이것을 수행하는 것이 내장되어 있다고 믿지 않습니다 .

답변2

$?변수를 사용하여 wget의 반환 코드를 가져올 수 있습니다. 0이 아닌 경우 오류가 발생했음을 의미하며 임계값에 도달할 때까지 이를 계산한 다음 루프에서 벗어날 수 있습니다.

이런게 떠오르네요

#!/bin/bash

threshold=0
for x in {90..110}; do
    wget 'http://www.iqandreas.com/sample-images/100-100-color/'$x'.jpg'
    wgetreturn=$?
    if [[ $wgetreturn -ne 0 ]]; then
        threshold=$(($threshold+$wgetreturn))
        if [[ $threshold -eq 16 ]]; then
                break
        fi
    fi
done

for 루프는 약간 정리될 수 있지만 일반적인 아이디어를 얻을 수 있습니다.

$threshold -eq 16중지하기 전에 3번 실패한다는 의미 로 변경되었습니다 -eq 24. 그러나 연속 두 번이 아니라 루프에서 두 번 실패하면 실패합니다.

16sum을 사용하는 이유 24는 반환 코드의 합이기 때문입니다. wget은 서버로부터 오류에 해당하는 응답 코드를 받으면
반환 코드로 응답하므로 총 2개의 오류가 발생합니다.816

실패가 연속 두 번만 발생하는 경우 중지하려면 wget성공 시 임계값을 재설정하면 됩니다(예: 반환 코드가 0인 경우).


wget 반환 코드 목록은 여기에서 찾을 수 있습니다.http://www.gnu.org/software/wget/manual/html_node/Exit-Status.html

답변3

종료 코드/상태 에 초점을 맞춘 IMO는 wget일부 사용 사례에서는 너무 순진할 수 있으므로 여기에서는 몇 가지 세부적인 결정과 함께 HTTP 상태 코드도 고려됩니다.

wget명령의 HTTP 응답 헤더를 -S/--server-response인쇄하기 위한 플래그를 제공합니다 . 해당 헤더를 추출하여 작업할 수 있습니다.STDERR

#!/bin/bash

set -eu

error_max=2
error_count=0

urls=( 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg' )

for url in "${urls[@]}"; do
  set +e
  http_status=$( wget --server-response -c "$url" 2>&1 )
  exit_status=$?
  http_status=$( awk '/HTTP\//{ print $2 }' <<<"$http_status" | tail -n 1 )

  if (( http_status >= 400 )); then
    # Considering only HTTP Status errors
    case "$http_status" in
      # Define your actions for each 4XX Status Code below
      410) : Gone
        ;;
      416) : Requested Range Not Satisfiable
        error_count=0  # Reset error_count in case of `wget -c`
        ;;
      403) : Forbidden
        ;&
      404) : Not Found
        ;&
      *)     (( error_count++ ))
        ;;
    esac
  elif (( http_status >= 300 )); then
     # We're unlikely to reach here in case of 1XX, 3XX in $http_status
     # but ..
     exit_status=0
  elif (( http_status >= 200 )); then
     # 2XX in $http_status considered successful
     exit_status=0
  elif (( exit_status > 0 )); then

    # Where wget's exit status is one of
    # 1   Generic error code.
    # 2   Parse error 
    #     - when parsing command-line options, the .wgetrc or .netrc...
    # 3   File I/O error.
    # 4   Network failure.
    # 5   SSL verification failure.
    # 6   Username/password authentication failure.
    # 7   Protocol errors.

    (( error_count++ ))
  fi

  echo "$url -> http_status: $http_status, exit_status=$exit_status, error_count=$error_count" >&2

  if (( error_count >= error_max )); then
    echo "error_count $error_count >= $error_max, bailing out .." >&2
    exit "$exit_status"
  fi

done

답변4

내가 성공적으로 사용한 것은

wget 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg' 2>&1 | grep -q 'ERROR 404: Not Found'

grep -q입력에서 404 오류 메시지 패턴을 찾아보고 표시되는 즉시 종료하십시오. 더 이상 읽을 수 없는 파이프 wget에 쓰려고 시도하자마자 SIGPIPE 신호가 수신됩니다. grep실제로 wget첫 번째 404 오류를 받은 후 곧 종료됩니다.

관련 정보