Intereting Posts
«Подсчитайте, сколько разных начальных букв написано в именах языков» Почему я должен использовать «sudo», когда нахожусь в группе суперпользователей? Захват определенного столбца из вывода команды Удаленный доступ к cassandra, работающему на локальном шлейфе IP / port 127.0.0.1 запустить команду по скрипту в алфавитном порядке Какой самый простой способ настроить двухчасовую тревогу? Не удалось запустить графический интерфейс Как зарезервированные блоки GDT используются после изменения размера сети в файловой системе ext3 Скопируйте только обычные файлы из одного каталога в другой круглый робин для завитки и dnsmasq Сделать поисковый снимок после каталогов? пытается установить драйверы amd Настройка CentOS7.0 – размер раздела Как драйвер wifi подвергается воздействию пользовательского пространства? Как пропустить уведомление по электронной почте для команды в AIX?

Как вы остановите «wget» после того, как он получит 404?

Если вы используете расширение скобки с помощью wget , вы можете легко получить последовательные пронумерованные изображения:

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

Он извлекает первые 10 файлов с номером 90.jpg до 99.jpg просто отлично, но 100.jpg и вперед возвращают 404: Ошибка файла не найдена (у меня есть только 100 изображений, хранящихся на сервере). Эти несуществующие файлы становятся более «проблемными», если вы используете более широкий диапазон, например {00..200} , с 100 несуществующими файлами, это увеличивает время выполнения скрипта и может даже стать небольшим бременем ( или, по крайней мере, раздражение) на сервере.

Есть ли способ для wget остановиться после того, как он получил свою первую ошибку 404? (или даже лучше, два подряд, в случае отсутствия недостающего файла в диапазоне по другой причине). Ответ не требует использования расширения скобок; петли тоже прекрасны.

Если вы довольны циклом:

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

Это запустит wget для каждого 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 есть что-то встроенное для этого.

Вы можете использовать $? переменной, чтобы получить код возврата 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 отвечает кодом возврата 8 когда он получает код ответа, соответствующий ошибке с сервера, и, таким образом, 16 является суммой после 2 ошибок.

Остановка, когда ошибки происходят только дважды подряд, может быть выполнена путем сброса порога всякий раз, когда wget преуспевает, т.е. когда код возврата равен 0


Список кодов возврата wget можно найти здесь – http://www.gnu.org/software/wget/manual/html_node/Exit-Status.html

С GNU Parallel это должно работать:

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

Начиная с версии 20140722, вы можете почти потерять «два в ряд»: -halt 2% позволит выполнить 2% заданий:

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

IMO, ориентируясь на код / ​​статус выхода wget может быть слишком наивна для некоторых случаев использования, поэтому здесь приведен пример кода состояния 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 

В python вы можете сделать

 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