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


12

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

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

이 번호가 처음 10 개 파일을 가져 오는 90.jpg99.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 번 실패 의미, 그것은 것입니다.

이유 1624사용은이 리턴 코드의 총입니다.
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.