wget을 사용하여 여러 파일을 병렬로 다운로드

wget을 사용하여 여러 파일을 병렬로 다운로드

다음 bash 스크립트가 있습니다.

for i in {0800..9999}; do
    for j in {001..032}; do
        wget http://example.com/"$i-$j".jpg
    done
done

모든 사진이 거기에 있으며 실제로 각 반복은 다른 반복에 종속되지 않습니다. 스레드 수를 병렬화하고 제어하는 ​​방법은 무엇입니까?

답변1

Confiq의 답변은 작은 i합계 에 대해 잘 작동합니다 j. 그러나 질문의 i​​합계 크기를 고려하면 j생성되는 총 프로세스 수를 제한할 수 있습니다. parallel명령이나 일부 버전을 사용할 수 있습니다 xargs. 예를 들어 -P이 플래그를 지원하는 xargs를 사용하면 다음과 같이 내부 루프를 병렬화할 수 있습니다.

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

GNU 병렬더 복잡한 동작이 필요할 때 수많은 기능을 제공하며 다음 두 매개변수를 사용하여 쉽게 병렬화할 수 있습니다.

parallel -a <(seq 0800 9999) -a <(seq 001 032) -P 8 wget http://example.com/{1}-{2}.jpg

답변2

이것은 매우 간단한 방법입니다. 이 예에서는 스레드를 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

답변3

for i in {1..3}; do
    for j in {10..20}; do
        (wget http://example.com/"$i-$j".jpg &)
    done
done

테스트도 해봤는데..

답변4

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(개행에 주의하세요!). $MAX_CONCURRENT동시 프로세스를 생성하여 $n생성된 프로세스 수를 추적하고 $PIDS해당 프로세스 ID를 기록합니다. 프로세스가 생성 되면 $MAX_CONCURRENT(실제로 생성되는 것은 복합 명령문이므로 여러 명령 또는 블록을 포함할 수 있음) wait생성된 PID에 있게 됩니다(또는 지정된 PID가 아직 실행되고 있지 않으면 즉시 반환됩니다). 다른 실행을 계속하기 전에 내부 상태를 재설정합니다.

재사용된 PID를 더 잘 처리하는 것을 포함하여 이 스크립트를 개선할 수 있는 방법이 있지만 실행해야 하는 환경에서 내가 원하는 작업을 수행하므로 나에게는 충분합니다. 실제 버전에서는 시간 제한도 설정하고 cron을 통해 주기적으로 실행을 다시 실행하므로 이 간단한 버전에 비해 실행 시간 폭주 위험이 크게 줄어듭니다.

관련 정보