它是什么?
GNU Parallel是一个shell工具,为了在一台或多台计算机上并行的执行计算任务,一个计算任务可以是一条shell命令或者一个以每一行做为输入的脚本程序。通常的输入是文件列表、主机列表、用户列表、URL列表或者表格列表;一个计算任务也可以是一个从管道读取的一条命令。GNU Parallel会把输入分块,然后通过管道并行的执行。
如果你会使用xargs和tee命令,你会发现GNU Parallel非常易于使用,因为GNU Parallel具有与xargs一样的选项。GNU Parallel可以替代大部分的shell循环,并且用并行的方式更快的完成计算任务。
GNU Parallel保证它的输出与顺序执行计算任务时是一样的,这样就可以方便的把GNU Parallel的输出做为其它程序的输入。
对于每一行输入,GNU Parallel会把这一行做为参数来运行指定的命令。如果没有给出命令,那么这一行会被当做命令执行。多行输入会并行的运行。GNU Parallel经常被用于替代xargs或者cat | bash。
指南
本教程展示了绝大多数GNU Parallel的功能。旨在介绍GNU Parallel中的一个选项,而非讲解真实世界中使用的例子。花一个小时的时间学习本教程,你会由此爱上上命令行。
预备
为了执行本教程中的示例,你首先需要做如下准备:
parallel >= version 20130814
安装最新版:
代码语言:javascript复制(wget -O - pi.dk/3 || curl pi.dk/3/) | bash
这条命令同时也会安装最新版的指南
代码语言:javascript复制man parallel_tutorial
本教程的大部分内容同时也兼容旧版本。
abc-file
生成文件:
代码语言:javascript复制parallel -k echo ::: A B C > abc-file
def-file
生成文件:
代码语言:javascript复制parallel -k echo ::: D E F > def-file
abc0-file
生成文件:
代码语言:javascript复制perl -e 'printf "Aperl -e 'printf "A B C "' > abc0-fileBperl -e 'printf "A B C "' > abc0-fileCperl -e 'printf "A B C "' > abc0-file"' > abc0-file
abc_-file
生成文件:
代码语言:javascript复制perl -e 'printf "A_B_C_"' > abc_-file
tsv_file.tsv
生成文件:
代码语言:javascript复制perl -e 'printf "f1tf2nAtBnCtDn"' > tsv-file.tsv
num30000
生成文件:
代码语言:javascript复制perl -e 'for(1..30000){print "$_n"}' > num30000
num1000000
生成文件:
代码语言:javascript复制perl -e 'for(1..1000000){print "$_n"}' > num1000000
num_%header
生成文件:
代码语言:javascript复制(echo %head1; echo %head2; perl -e 'for(1..10){print "$_n"}') > num_%header
远程执行:ssh免密码登录SERVER1和SERVER2
生成文件:
代码语言:javascript复制SERVER1=server.example.com
SERVER2=server2.example.net
最后应该成功运行如下命令:
代码语言:javascript复制ssh $SERVER1 echo works
ssh $SERVER2 echo works
使用 ssh-keygen -t dsa; ssh-copy-id $SERVER1 建立环境(使用empty pass phrase)
输入源
GNU Parallel的输入源支持文件、命令行和标准输入(stdin或pipe)
单个输入源
从命令行读取输入:
代码语言:javascript复制parallel echo ::: A B C
输出(由于任务以并行的方式执行,顺序可能会有所不同):
A B C
文件做为输入源:
代码语言:javascript复制parallel -a abc-file echo
输出同上。
STDIN(标准输入)做为输入源:
代码语言:javascript复制cat abc-file | parallel echo
输出同上。
多输入源
GNU Parallel支持通过命令行指定多个输入源,它会生成所有的组合:
代码语言:javascript复制parallel echo ::: A B C ::: D E F
输出:
A D A E A F B D B E B F C D C E C F
多个文件做为输入源:
代码语言:javascript复制parallel -a abc-file -a def-file echo
输出同上。
STDIN(标准输入)可以做为输入源中的一个,使用“-”:
代码语言:javascript复制cat abc-file | parallel -a - -a def-file echo
输出同上。
可以使用“::::”替代 -a:
代码语言:javascript复制cat abc-file | parallel echo :::: - def-file
输出同上。
::: 和 :::: 可以混合使用:
代码语言:javascript复制parallel echo ::: A B C :::: def-file
输出同上。
适配参数
–xapply 从每一个输入源取一个参数:
代码语言:javascript复制parallel --xapply echo ::: A B C ::: D E F
输出:
A D B E C F
如果其中一个输入源的长度比较短,它的值会被重复:
代码语言:javascript复制parallel --xapply echo ::: A B C D E ::: F G
输出:
A F B G C F D G E F
改变参数分隔符
GNU Parallel可以指定分隔符替代 ::: 或 ::::,当这两个符号被其它命令占用的时候会特别有用:
代码语言:javascript复制parallel --arg-sep ,, echo ,, A B C :::: def-file
输出:
A D A E A F B D B E B F C D C E C F
改变参数分隔符:
代码语言:javascript复制parallel --arg-file-sep // echo ::: A B C // def-file
输出同上。
改变参数定界符
GNU Parallel默认把一行做为一个参数:使用 n 做为参数定界符。可以使用 -d 改变:
代码语言:javascript复制parallel -d _ echo :::: abc_-file
输出:
A B C