다음 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을 통해 주기적으로 실행을 다시 실행하므로 이 간단한 버전에 비해 실행 시간 폭주 위험이 크게 줄어듭니다.