在 'wget' 收到 404 错误后如何停止它?

在 'wget' 收到 404 错误后如何停止它?

如果将大括号扩展与 一起使用wget,则可以轻松获取按顺序编号的图像:

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

它获取前 10 个编号90.jpg99.jpg就好的文件,但是100.jpg然后返回一个404:找不到文件错误(我的服务器上只存储了 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

这将为扩展中的每个 URL 运行,wget直到失败,然后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 的返回码。如果它非零,则意味着发生了错误,并且您对其进行计数直到达到阈值,然后它可能会跳出循环。

我的脑海里浮现出这样的事情

#!/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 收到与来自服务器的错误相对应的响应代码时,
它会使用返回代码进行响应,因此是 2 个错误后的总数。816

当失败仅连续发生两次时停止可以通过在wget成功时重置阈值来完成,即当返回码为 0 时


wget 返回代码的列表可以在这里找到 -http://www.gnu.org/software/wget/manual/html_node/Exit-Status.html

答案3

IMO,关注 的wget退出代码/状态对于某些用例来说可能太天真,因此这里也考虑了 HTTP 状态代码以及一些细粒度的决策。

wget提供一个-S/--server-response标志来打印STDERR命令的 HTTP 响应标头 - 我们可以提取该标头并对其进行操作。

#!/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一旦尝试写入grep不再读取的管道,就会收到 SIGPIPE 信号。实际上,wget在收到第一个 404 错误后很快就会死亡。

相关内容