Параллельный wget в Bash [дубликат]
этот вопрос уже есть ответ здесь:
загрузка wget с несколькими одновременными соединениями
13 ответов
Я получаю кучу относительно небольших страниц с веб-сайта и задавался вопросом, Могу ли я как-то сделать это параллельно в Bash. В настоящее время мой код выглядит так, но для его выполнения требуется некоторое время (я думаю, что это замедление меня-это задержка в соединении).
for i in {1..42}
do
wget "https://www.example.com/page$i.html"
done
Я слышал об использовании xargs, но я ничего не знаю об этом, и страница man очень запутана. Есть идеи? Можно ли вообще делать это параллельно? Есть ли другой способ, которым я мог бы атаковать это?
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