Загрузить несколько файлов с помощью wget параллельно

В Fedora 25, settings/universal access/typing/repeat keys, установите значение off, чтобы полностью отключить залипание клавиш или настроить задержку и скорость по своему вкусу

7
31.07.2017, 14:19
4 ответа

Ответ Confiq хорош для небольших iи j. Однако, учитывая размер iи jв вашем вопросе, вы, вероятно, захотите ограничить общее количество порожденных процессов. Вы можете сделать это с помощью команды parallelили некоторых версий xargs. Например, используя xargs, который поддерживает флаг -P, вы можете распараллелить свой внутренний цикл следующим образом:

for i in {0800..9999}; do
  echo {001..032} | xargs -n 1 -P 8 -I{} wget http://example.com/"$i-{}".jpg
done

GNU parallel имеет большое количество функций, когда вам нужно более сложное поведение, и упрощает распараллеливание по обоим параметрам:

parallel -a <(seq 0800 9999) -a <(seq 001 032) -P 8 wget http://example.com/{1}-{2}.jpg
22
27.01.2020, 20:13
for i in {1..3}; do
    for j in {10..20}; do
        (wget http://example.com/"$i-$j".jpg &)
    done
done

Я даже проверял...

3
27.01.2020, 20:13

Вот очень упрощенный подход. Ограничивает потоки до 10 в этом примере.

for i in {0800..9999}; do
    for j in {001..032}; do
        wget http://example.com/"$i-$j".jpg &
        while test $(jobs -p|wc -w) -ge 10; do sleep 0.1 ; done
    done
done
4
27.01.2020, 20:13

Примерно так я решил ту же проблему в среде, где parallelне было доступно. Это зависит от функций bash, поэтому вам нужно #!/bin/bashили явно выполнить скрипт через bash.

MAX_CONCURRENT=50
n=0
some_command_that_outputs_urls \
| while read url
do
    {
        do_something_with $url
    } &
    PIDS="$PIDS $!"

    ((++n))
    if test "$n" -ge "$MAX_CONCURRENT"
    then
        n=0
        wait $PIDS
        PIDS=""
    fi
done
test -n "$PIDS" && wait $PIDS

Можно настроить $MAX_CONCURRENT, чтобы указать желаемое (приблизительное )максимальное количество потоков. И, конечно же, вы замените some_command_that_outputs_urlsи do_something_with $urlтем, что подходит для вашего сценария. Например, вы можете заменить строку some_command_that_outputs_urls \на

.
for i in {0800..9999}; do
    for j in {001..032}; do
        printf 'http://example.com/%s-%s.jpg\n' $i $j
    done
done \
#...| while read url...

и do_something_with $urlпросто с

wget $url

окончательный результат

MAX_CONCURRENT=50
n=0
for i in {0800..9999}; do
    for j in {001..032}; do
        printf 'http://example.com/%s-%s.jpg\n' $i $j
    done
done \
| while read url
do
    {
        wget $url
    } &
    PIDS="$PIDS $!"

    ((++n))
    if test "$n" -ge "$MAX_CONCURRENT"
    then
        n=0
        wait $PIDS
        PIDS=""
    fi
done
test -n "$PIDS" && wait $PIDS

Это работает следующим образом: команда генерирует список (в данном случае )URL-адресов на своем стандартном выходе и считывает эту строку за раз в цикл while(watch для новых строк! ). Он будет порождать до $MAX_CONCURRENTодновременных процессов, используя $nдля отслеживания количества порожденных процессов и $PIDSдля записи их идентификаторов процессов. После того, как $MAX_CONCURRENTпроцессы были порождены (, обратите внимание, что то, что действительно порождается, является составным оператором, поэтому вы можете иметь несколько команд и даже блоков внутри него ), это будет waitна порожденных PID (это немедленно возвращается, если ни один из указанных PID все еще не выполняется )и сбрасывает свое внутреннее состояние, затем переходит к другому запуску.

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

2
27.01.2020, 20:13

Теги

Похожие вопросы