정렬하고 싶은 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개의 파일을 처리합니다.