Параллельный wget в Bash [дубликат]



этот вопрос уже есть ответ здесь:




  • загрузка wget с несколькими одновременными соединениями

    13 ответов



Я получаю кучу относительно небольших страниц с веб-сайта и задавался вопросом, Могу ли я как-то сделать это параллельно в Bash. В настоящее время мой код выглядит так, но для его выполнения требуется некоторое время (я думаю, что это замедление меня-это задержка в соединении).



for i in {1..42}
do
wget "https://www.example.com/page$i.html"
done


Я слышал об использовании xargs, но я ничего не знаю об этом, и страница man очень запутана. Есть идеи? Можно ли вообще делать это параллельно? Есть ли другой способ, которым я мог бы атаковать это?

678   5  

5 ответов:

гораздо предпочтительнее, толкая wget в фоновом режиме, используя & или -b, вы можете использовать xargs С тем же эффектом, и лучше.

преимущество в том, что xargs будет правильной синхронизации без дополнительной работы. Это означает, что вы можете безопасно получить доступ к загруженным файлам (при условии, что ошибка не возникает). Все загрузки будут завершены (или не удалось) один раз xargs выход, и вы знаете код выхода, все ли прошло хорошо. Это гораздо предпочтительнее к занятому ожиданию с sleep и тестирование для завершения вручную.

предполагая, что URL_LIST - это переменная, содержащая все URL-адреса (может быть построена с циклом в Примере OP, но также может быть сгенерированным вручную списком), выполняющая это:

echo $URL_LIST | xargs -n 1 -P 8 wget -q

будет передавать по одному аргументу за раз (-n 1) к wget, и выполнить не более 8 параллельных wget процессы одновременно (-P 8). xarg возвращается после завершения последнего порожденного процесса, который просто то, что мы хотели знать. Никаких дополнительных хитростей не требуется.

"магическое число" из 8 параллельных загрузок, которые я выбрал, не установлено в камне, но это, вероятно, хороший компромисс. Есть два фактора в "максимизации" серии загрузок:

один заполняет "кабель", т. е. используя доступную полосу пропускания. Предполагая "нормальные" условия (сервер имеет большую пропускную способность, чем клиент), это уже происходит с одной или, самое большее, двумя загрузками. Бросая больше соединений на проблема приведет только к отбрасыванию пакетов и запуску управления перегрузкой TCP, и N загрузка с асимптотически 1/N пропускная способность каждого, к тому же чистому эффекту (минус отброшенные пакеты, минус восстановление размера окна). Отбрасывание пакетов-это нормальная вещь, которая происходит в IP-сети, именно так должен работать контроль перегрузки (даже с одним соединением), и обычно влияние практически равно нулю. Однако, слишком большие количество соединений усиливает этот эффект, поэтому он может быть заметен. В любом случае, это не делает ничего быстрее.

второй фактор-это установление соединения и обработка запроса. Здесь, имея несколько дополнительных соединений в полете помогает. Проблема, с которой приходится сталкиваться,-это задержка двух поездок туда и обратно (обычно 20-40ms в пределах одной географической области, 200-300ms inter-continental) плюс нечетные 1-2 миллисекунды, которые сервер фактически должен обработайте запрос и нажмите ответ на сокет. Это не так много времени per se, но умноженный на несколько сотен/тысяч запросов, он быстро складывается.
Наличие чего-либо от полудюжины до десятка запросов в полете скрывает большую часть или всю эту задержку (она все еще существует, но поскольку она перекрывается, она не суммируется!). В то же время наличие только нескольких параллельных соединений не оказывает неблагоприятного воздействия, такого как чрезмерная перегрузка или принудительное использование сервера в разветвление новых процессов.

просто запуск заданий в фоновом режиме не является масштабируемым решением: если вы получаете 10000 URL-адресов, вы, вероятно, хотите получить только несколько (скажем, 100) параллельно. GNU Parallel создан для этого:

seq 10000 | parallel -j100 wget https://www.example.com/page{}.html

дополнительные примеры см. На справочной странице: http://www.gnu.org/software/parallel/man.html#example__download_10_images_for_each_of_the_past_30_days

можно использовать :

wget -b "https://www.example.com/page$i.html"

если вы не хотите файлы журнала, добавьте опцию -o /dev/null.

-o FILE  log messages to FILE.

добавление амперсанда к команде заставляет его работать в фоновом режиме

for i in {1..42}
do
    wget "https://www.example.com/page$i.html" &
done

версия 2 wget, похоже, реализует несколько соединений. Ссылка на проект в github:https://github.com/rockdaboot/wget2

Comments

    Ничего не найдено.