Bash 스크립트 처리 제한된 수의 명령 병렬


196

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

#!/bin/bash
wget LINK1 >/dev/null 2>&1
wget LINK2 >/dev/null 2>&1
wget LINK3 >/dev/null 2>&1
wget LINK4 >/dev/null 2>&1
# ..
# ..
wget LINK4000 >/dev/null 2>&1

그러나 명령이 완료 될 때까지 각 줄을 처리 한 다음 다음 줄로 이동하는 데 시간이 많이 걸리므로 한 번에 20 줄을 처리 한 다음 다른 20 줄을 처리하려고합니다.

나는 wget LINK1 >/dev/null 2>&1 &명령을 백그라운드로 보내고 계속 생각 했지만 여기에 4000 줄이 있습니다. 이것은 성능 문제가 있음을 의미합니다. 생각.

내가 지금 생각하고있는 한 가지 해결책은 명령 중 하나가 여전히 실행 중인지 여부를 확인하는 것입니다. 예를 들어 20 줄 이후 에이 루프를 추가 할 수 있습니다.

while [  $(ps -ef | grep KEYWORD | grep -v grep | wc -l) -gt 0 ]; do
sleep 1
done

물론이 경우 줄 끝에 &를 추가해야합니다! 그러나 이것이 올바른 방법이 아니라고 생각합니다.

따라서 실제로 각 20 줄을 그룹화하고 다음 20 줄로 이동하기 전에 완료 될 때까지 기다리는 방법은 무엇입니까?이 스크립트는 동적으로 생성되므로 생성되는 동안 원하는 수학을 수행 할 수 있지만 반드시 할 필요는 없습니다. wget을 사용하십시오. 이것은 단지 예 일뿐이므로 wget과 관련된 솔루션은 나에게 도움이되지 않습니다.


1
wait여기에 정답이지만, proctools를 사용하는 while [ $(ps …것이 훨씬 좋습니다 . 즉, 특정 이름을 가진 프로세스가 여전히 실행 중인지 확인해야하는 합법적 인 이유 때문입니다. while pkill -0 $KEYWORD…
kojiro

이 질문을 다시 열어야한다고 생각합니다. "가능한 복제"QA는 유한 한 수의 프로그램을 병렬로 실행하는 것 입니다. 2-3 명령과 같습니다. 그러나이 질문은 루프에서 명령을 실행하는 데 중점을 둡니다. ( "4000 줄이 있습니다"참조).
VasiliNovikov

@VasyaNovikov 이 질문과 중복에 대한 모든 답을 읽었 습니까? 이 질문에 대한 모든 단일 답변은 중복 질문에 대한 답변에서도 찾을 수 있습니다. 그것은 정확히 중복 질문의 정의입니다. 루프에서 명령을 실행하는지 여부는 전혀 차이가 없습니다.
robinCTS

@robinCTS에는 교차점이 있지만 질문 자체는 다릅니다. 또한 연결된 QA에서 가장 인기있는 답변 중 6 개는 2 개의 프로세스 만 처리합니다.
VasiliNovikov

2
이 질문에 대한 답변은 링크 된 질문에 대한 답변보다 명확하고, 깨끗하며, 우수하며, 훨씬 더 많이지지되기 때문에이 질문을 다시 여는 것이 좋습니다.
Dan Nissenbaum

답변:


331

wait내장을 사용하십시오 .

process1 &
process2 &
process3 &
process4 &
wait
process5 &
process6 &
process7 &
process8 &
wait

위의 예를 들어, 4 개 과정은 process1... process4백그라운드에서 시작된다, 그 다음 세트를 시작하기 전에 완료 될 때까지 쉘은 기다릴 것입니다.

로부터 GNU 설명서 :

wait [jobspec or pid ...]

각 프로세스 ID pid 또는 작업 스펙 jobspec에 의해 지정된 하위 프로세스가 종료 될 때까지 기다렸다가 마지막으로 대기 한 명령의 종료 상태를 리턴하십시오. 작업 스펙이 제공되면 작업의 모든 프로세스가 대기합니다. 인수가 제공되지 않으면 현재 활성화 된 모든 하위 프로세스가 대기되고 리턴 상태는 0입니다. jobspec 또는 pid가 쉘의 활성 하위 프로세스를 지정하지 않으면 리턴 상태는 127입니다.


14
기본적으로i=0; waitevery=4; for link in "${links[@]}"; do wget "$link" & (( i++%waitevery==0 )) && wait; done >/dev/null 2>&1
kojiro

18
각 프로세스가 동시에 완료 될 것이라고 확신하지 않는 한 이것은 나쁜 생각입니다. 현재 총 작업을 특정 한도로 유지하려면 새 작업을 시작해야합니다. 병렬 이 답입니다.
rsaw

1
루프에서 이것을 수행하는 방법이 있습니까?
DomainsFeatured

나는 이것을 시도했지만 한 블록에서 수행 된 변수 할당은 다음 블록에서 사용할 수없는 것 같습니다. 그것들은 별도의 프로세스이기 때문에입니까? 변수를 주 프로세스와 다시 통신하는 방법이 있습니까?
바비

97

parallel 참조하십시오 . 구문은와 비슷 xargs하지만 명령을 병렬로 실행합니다.


13
wait다음을 시작하기 전에 전체 배치가 완료되기를 기다리는 대신 이전 작업이 완료되면 새 작업을 시작하는 것을 처리하므로이 방법을 사용하는 것보다 낫습니다 .
chepner

5
예를 들어, 파일에 링크 목록이있는 경우 한 번에 cat list_of_links.txt | parallel -j 4 wget {}4 개씩 wget실행되도록 할 수 있습니다.
Mr. Llama

5
도시라는 새로운 아이가 pexec 를 대체합니다 parallel.
슬래시 빈

2
예제를 제공하는 것이 더 도움이 될 것입니다
jterm

1
parallel --jobs 4 < list_of_commands.sh여기서 list_of_commands.sh는 모든 행에 단일 명령 (예 :을 포함 wget LINK1하지 않는 메모 &) 이있는 파일입니다 . 할 필요가있다 CTRL+Zbg후에는 백그라운드에서 실행을 떠나.
weiji14

71

실제로 명령을 병렬로 실행할 xargs 있습니다. 특별한 -P max_procs명령 행 옵션이 있습니다. 참조하십시오 man xargs.


2
+100 이것은 내장되어 있고 사용하기 매우 간단하고 한 라이너로 할 수 있기 때문에 훌륭합니다
Clay

추가 패키지 / 종속성이 필요하지 않으므로 작은 컨테이너에 사용하기 좋습니다!
Marco Roy

1
예를
Marco Roy

7

20 개의 프로세스를 실행하고 다음 명령을 사용할 수 있습니다.

wait

모든 백그라운드 작업이 완료되면 스크립트가 대기하고 계속됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.