program tip

Bash의 병렬 wget

radiobox 2020. 11. 6. 08:01
반응형

Bash의 병렬 wget


이 질문에 이미 답변이 있습니다.

나는 웹 사이트에서 비교적 작은 페이지를 많이 얻고 있으며 어떻게 든 Bash에서 병렬로 할 수 있는지 궁금합니다. 현재 내 코드는 다음과 같이 보이지만 실행하는 데 시간이 걸립니다 (저를 느리게하는 것은 연결 대기 시간이라고 생각합니다).

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

xargs 사용에 대해 들어 봤지만 그것에 대해 아무것도 모르고 man 페이지가 매우 혼란 스럽습니다. 어떤 아이디어? 이 작업을 병렬로 수행 할 수도 있습니까? 이것을 공격하는 다른 방법이 있습니까?


밀어 훨씬보다 더 낫다 wget사용하여 배경으로 &하거나 -b, 사용할 수있는 xargs동일한 효과를, 그리고 더 나은.

장점은 추가 작업없이 제대로 동기화 된다는 xargs입니다. 즉, 다운로드 한 파일에 안전하게 액세스 할 수 있습니다 (오류가 발생하지 않는다고 가정). 종료 되면 모든 다운로드가 완료 (또는 실패) 되며 종료 코드로 모든 것이 잘되었는지 여부를 알 수 있습니다. 이것은 수동으로 완료를 위해 대기 하고 테스트하는 것보다 훨씬 선호됩니다 .xargssleep

이것이 URL_LIST모든 URL을 포함하는 변수 라고 가정하고 (OP의 예에서 루프로 구성 할 수 있지만 수동으로 생성 된 목록 일 수도 있음) 다음을 실행합니다.

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

한 번에 하나의 인수 ( -n 1)를에 전달하고 한 번 wget에 최대 8 개의 병렬 wget프로세스를 실행 합니다 ( -P 8). xarg마지막으로 생성 된 프로세스가 완료된 후 반환됩니다. 이것은 우리가 알고 싶었던 것입니다. 추가 속임수가 필요하지 않습니다.

내가 선택한 8 개의 병렬 다운로드의 "매직 넘버"는 확정 된 것은 아니지만 아마도 좋은 타협점 일 것입니다. 일련의 다운로드를 "최대화"하는 데는 두 가지 요소가 있습니다.

하나는 "케이블"을 채우는 것, 즉 사용 가능한 대역폭을 활용하는 것입니다. "정상"조건 (서버가 클라이언트보다 더 많은 대역폭을 가짐)을 가정하면 이미 한 번 또는 최대 두 번의 다운로드가있는 경우입니다. 문제에 더 많은 연결을 던지면 패킷이 삭제되고 TCP 혼잡 제어가 시작되고 점근 적으로 1 / N으로 N 개의 다운로드가 발생합니다.대역폭을 각각 동일한 순 효과 (삭제 된 패킷 제외, 창 크기 복구 제외)로 설정합니다. 드롭되는 패킷은 IP 네트워크에서 발생하는 정상적인 현상이며, 이는 혼잡 제어가 작동하는 방식 (단일 연결에서도)이며 일반적으로 영향은 거의 0입니다. 그러나 불합리하게 많은 수의 연결이 있으면이 효과가 증폭되므로 눈에 띄게 나타날 수 있습니다. 어쨌든 그것은 아무것도 더 빨리 만들지 않습니다.

두 번째 요소는 연결 설정 및 요청 처리입니다. 여기에서 비행 중에 몇 개의 추가 연결이 있으면 정말 도움이됩니다 . 하나가 직면 한 문제는 두 번의 왕복 (일반적으로 동일한 지리적 영역 내에서 20-40ms, 대륙간 200-300ms)의 지연 시간과 서버가 실제로 요청을 처리하고 응답을 푸시하는 데 필요한 홀수 1-2 밀리 초입니다. 소켓에. 이것은 그 자체 로 많은 시간이 아니지만 수백 / 천개의 요청을 곱하면 빠르게 합산됩니다.
진행중인 요청이 6 개에서 12 개까지 있으면이 지연 시간의 대부분 또는 전부가 숨겨집니다 (여전히 존재하지만 겹치기 때문에 요약되지 않습니다!). 동시에 몇 개의 동시 연결 만 있으면 과도한 혼잡을 유발하거나 서버가 새 프로세스를 분기하도록하는 등의 부작용이 없습니다.


백그라운드에서 작업을 실행하는 것은 확장 가능한 솔루션이 아닙니다. 10000 개의 URL을 가져 오는 경우 병렬로 몇 개 (예 : 100 개) 만 가져오고 싶을 것입니다. GNU Parallel은 다음을 위해 만들어졌습니다.

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

더 많은 예제는 man 페이지를 참조하십시오 : http://www.gnu.org/software/parallel/man.html#example__download_10_images_for_each_of_the_past_30_days


-b옵션 을 사용할 수 있습니다 .

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

로그 파일을 원하지 않는 경우 옵션을 추가하십시오 -o /dev/null.

-o FILE 로그 메시지를 FILE에.

명령에 앰퍼샌드를 추가하면 백그라운드에서 실행됩니다.

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

wget의 버전 2는 다중 연결을 구현하는 것 같습니다. github의 프로젝트 링크 : https://github.com/rockdaboot/wget2

참고 URL : https://stackoverflow.com/questions/7577615/parallel-wget-in-bash

반응형