404를 얻은 후 'wget'을 어떻게 중지합니까?


12

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

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

이 번호가 처음 10 개 파일을 가져 오는 90.jpg에 99.jpg잘,하지만 100.jpg이후에도 반환 404 : 파일을 찾을 수 없습니다 (I는 서버에 저장된 100 개 이미지가) 오류가 발생했습니다. 존재하지 않는 파일은 {00..200}100 개의 존재하지 않는 파일 과 같이 더 큰 범위를 사용 하면 스크립트의 실행 시간이 증가하고 약간의 부담 (또는 적어도 성가신)이 될 수 있습니다. 서버.

wget첫 번째 404 오류를 수신 한 후 중지 할 수있는 방법이 있습니까? (또는 다른 이유로 범위 내에 파일이 누락 된 경우 두 줄로 더 나아집니다) 대답은 중괄호 확장을 사용할 필요가 없습니다. 루프도 괜찮습니다.


1
실시간 시나리오에서는 모든 URL을 눌러 상태를 알 수 있습니다. 지수 1, 2 or even n failures를 알 때 올바른 방법이 아닙니다 [begin .. end]. 왜 지정하는 것입니다 [1..200]만 100 이미지에가 알고 범위를 [1..100]. parallel프로세스 속도를 높이기 위해 동시 요청에 GNU 를 사용해 볼 수 있다고 생각합니다 .
— SparKot

1
열쇠는 @SparKot 내가 하지 말이고이 시리즈에서 알아 낸 한 때까지로 서버에서만 100 이미지가 알고, 나는 많은 이미지로 다운로드 스크립트를 원한다.
— IQAndreas

답변:


9

루프에 만족한다면 :

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

wget확장에 실패 할 때까지 break루프의 각 URL에 대해 실행 됩니다 .

연속으로 두 번의 실패를 원하면 조금 더 복잡해집니다.

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내장 된 것이 없다고 생각 합니다.


elif두 번째 예를 더 명확하게하기 위해 사용할 것을 제안 할 수 있습니까? 아마도 이런 것? gist.github.com/IQAndreas/84cae3f0193b67691ff2 ( thens와 같은 줄에 s 를 넣는 것을 포함하지 않고 한 줄만 추가 if)
— IQAndreas

그럴 수 있지. 한 줄짜리 번역은 지금 간단하지 않지만 어쨌든별로 좋지 않습니다.
— 마이클 호머

9

$?변수를 사용하여 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하기 -eq 24는 루프에 두 번 실패 할 경우이 두 번 연속되지 않을 것, 그것이 멈출 것 전에 3 번 실패 의미, 그것은 것입니다.

이유 16및 24사용은이 리턴 코드의 총입니다.
wget은 8서버에서 오류에 해당하는 응답 코드를 수신 할 때 리턴 코드로 응답하므로 162 오류 후의 총계입니다.

wget성공할 때마다 ( 예 : 리턴 코드가 0 일 때) 임계 값을 재설정하여 실패가 한 번에 두 번만 발생할 때 중지 할 수 있습니다.


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


2
답변에서 추론 할 수는 있지만 404 오류는 종료 코드를 반환 8하므로 매직 숫자 는 16및을 나타 24냅니다.
— IQAndreas

1
내 답변을 업데이트했습니다
— Lawrence

1
감사합니다 $?! 매우 유용한!
— neverMind9

2

GNU Parallel을 사용하면 다음과 같이 작동합니다.

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

20140722 버전에서 거의 "2 연속"실패가 발생할 수 있습니다. --halt 2 %는 작업의 2 %가 실패 할 수 있습니다.

parallel --halt 2% wget ::: 'http://www.iqandreas.com/sample-images/100-100-color/'{90..110}'.jpg'

1

wget종료 코드 / 상태 에 중점을 둔 IMO 는 일부 유스 케이스에 대해 너무 순진 할 수 있으므로 다음은 세부적인 의사 결정을 위해 HTTP 상태 코드를 고려하는 것입니다.

wget명령 -S/--server-response의 HTTP 응답 헤더를 인쇄 하는 플래그를 제공합니다.이 플래그 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

-1

파이썬에서는 할 수 있습니다

from subprocess import *

def main():
    for i in range(90, 110):
       try :
          url = "url/"+str(i)
          check_output(["wget", url])
       except CalledProcessError:
          print "Wget returned none zero output, quiting"
          sys.exit(0)

더 많은 https://docs.python.org/2/library/subprocess.html 을 수행하려면 하위 프로세스에 대한 설명서를 확인 하십시오.


하지 않는 check_output몇 가지 마술을 수행 주위 wget을 감지하는 404- 내가 거기에 적절한 검사가 여기에 있습니다 그래서 정말 질문에 대답하지 않는 생각하지 않는다.
— shalomb 2016 년

그렇습니다. 문서를 읽으십시오. stdout 또는 stderr에서 출력을 확인합니다. wget은 404에 대한 특정 코드를 가지고 있습니다
— briankip
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.