Shell

如何為 shell 任務創建有界隊列?

  • September 22, 2017

我有 1000 個要排序的 gzip 文件。

按順序執行此操作,該過程看起來非常簡單:

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

不確定上面的程式碼是否有效(如果我在某處犯了錯誤,請糾正我),但我希望你能理解這個想法。

無論如何,我想並行化 ungzip/sort 作業,以使整個事情更快。另外,我不想看到所有 1000 個程序同時執行。擁有一些具有可配置容量的有界作業隊列(如 Java 中的 BlockingQueue 或 .NET 中的 BlockingCollection)會很棒。在這種情況下,只有 10 個程序將並行執行。

是否可以在 shell 中執行此操作?

使用 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)。你愛你的命令行。

我會選擇make(1)這個任務——它不是 shell,但make(1)jobserver 幾乎正是你想要的,而且這個任務非常適合make(1)’s 的能力。請注意,行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)智能地只做完成任何事情所需的最少工作量。

引用自:https://unix.stackexchange.com/questions/26161