쉘 작업에 대한 제한된 대기열을 만드는 방법은 무엇입니까?

쉘 작업에 대한 제한된 대기열을 만드는 방법은 무엇입니까?

정렬하고 싶은 1000개의 gzip 압축 파일이 있습니다.

이 작업을 순서대로 수행하면 프로세스가 매우 간단해 보입니다.

find . -name *.gz -exec zcat {} | sort > {}.txt \;

위의 코드가 작동하는지 확실하지 않지만(어디서 실수를 했다면 수정해 주세요), 이해가 되셨으면 좋겠습니다.

어쨌든, 전체 프로세스를 더 빠르게 만들기 위해 ungzip/sort 작업을 병렬화하고 싶습니다. 또한 1000개의 프로세스가 동시에 실행되는 것을 보고 싶지 않습니다. 구성 가능한 용량을 갖춘 제한된 작업 큐(예: Java의 BlockingQueue 또는 .NET의 BlockingCollection)가 있으면 좋을 것입니다. 이 경우 10개의 프로세스만 병렬로 실행됩니다.

쉘에서 이 작업을 수행할 수 있습니까?

답변1

GNU 병렬 처리 사용:

find . -name *.gz | parallel --files 'zcat {} | sort' | parallel -X -j1 sort -m {} ';' rm {} > sorted

다음과 같이 간단하게 GNU Parallel을 설치할 수 있습니다.

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel

자세히 알아보려면 소개 비디오를 시청하세요.https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1이 튜토리얼(man parallel_tutorial)을 살펴보세요. 당신은 명령줄을 정말 좋아합니다.

답변2

저는 이 작업을 선택하겠습니다 make(1). 쉘은 아니지만 make(1)jobserver는 여러분이 원하는 것과 거의 정확히 일치하며 make(1)이 작업에 적합한 기능을 갖추고 있습니다. 줄의 gzip -cd시작 부분에는 탭이 들여쓰기되어 있습니다. 이것은 매우 중요합니다. ( make(1)가끔은 좀 오래된 것 같은 느낌도 들 때가 있습니다.)

$ cat Makefile 
TXT := $(wildcard *.gz)

all: $(TXT:.gz=.txt)

%.txt:%.gz
    gzip -cd $< | sort > $@
$ cp /usr/share/man/man2/*.gz .
$ ls -l
total 1992
-rw-r--r-- 1 sarnold sarnold  4447 2011-12-06 00:22 aa_change_hat.2.gz
-rw-r--r-- 1 sarnold sarnold  3977 2011-12-06 00:22 aa_change_profile.2.gz
-rw-r--r-- 1 sarnold sarnold  5082 2011-12-06 00:22 accept.2.gz
...
$ time make -j 10
gzip -cd aa_change_hat.2.gz | sort > aa_change_hat.2.txt
gzip -cd aa_change_profile.2.gz | sort > aa_change_profile.2.txt
gzip -cd accept.2.gz | sort > accept.2.txt
gzip -cd accept4.2.gz | sort > accept4.2.txt
gzip -cd access.2.gz | sort > access.2.txt
...
gzip -cd write.2.gz | sort > write.2.txt
gzip -cd writev.2.gz | sort > writev.2.txt

real    0m0.259s
user    0m0.190s
sys 0m0.020s
$ rm w*txt
$ make
gzip -cd wait.2.gz | sort > wait.2.txt
gzip -cd wait3.2.gz | sort > wait3.2.txt
gzip -cd wait4.2.gz | sort > wait4.2.txt
gzip -cd waitid.2.gz | sort > waitid.2.txt
gzip -cd waitpid.2.gz | sort > waitpid.2.txt
gzip -cd write.2.gz | sort > write.2.txt
gzip -cd writev.2.gz | sort > writev.2.txt
$ 

rm w*txt이 명령은 작업을 완료 make(1)하는 데 필요한 최소한의 작업만 지능적으로 수행합니다.

답변3

Google을 잠깐 살펴보면 다음과 같은 흥미로운 접근 방식을 알 수 있습니다.http://pebblesinthesand.wordpress.com/2008/05/22/a-srcipt-for-running-processes-in-parallel-in-bash/

for ARG in  $*; do
    command $ARG &
    NPROC=$(($NPROC+1))
    if [ "$NPROC" -ge 4 ]; then
        wait
        NPROC=0
    fi
done

답변4

GNU를 사용하면 xargs다음을 수행할 수 있습니다.

xargs -P4 -n 10 -r0a <(find . -name '*.gz' -type f -print0) sh -c '
  for file do
    zcat < "$file" | sort > "$file.txt"
  done' sh {} +

이는 최대 4개의 파일을 병렬로 호출하며 sh, 각 파일은 루프에서 순서대로 최대 10개의 파일을 처리합니다.

관련 정보