安装
官方文档指南
输入源
直接在命令行传递参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| $ echo ::: a b c e b a c e $ parallel echo ::: a b c e ::: f g j i a g a j a i b f b j b i b g c f c g c j c i e f e g a f e j e i
|
以文件作为输入
1 2 3 4 5
| -a file1 -a file2 或 :::: file1 :::: file2
|
1 2 3
| parallel -a abc-file echo parallel -a a.file -a b.file echo
|
这样子就可以并行输出文件 abc-file
的内容(默认情况下, 是无序的, 如果想有序, 则传参数 -k
即可)
以标准输输入作为输入 stdin
直接 -
后不接其他东西即可.
例如
1 2 3 4 5 6
| $ seq 5 | parallel echo - 2 4 3 1 5
|
混合
{% raw %}:::{% endraw %}
可以和 {% raw %}::::{% endraw %}
混合使用.
跳过空行
1
| parallel --no-run-if-empty
|
指定输入结束符
1 2 3
| $ parallel -E stop echo ::: A B stop C D A B
|
修改参数界定符
使用 NUL 作为办分割符
修改文件界定符
默认情况下 {% raw %}::::{% endraw %}
作为文件的分界符, 可以使用
来修改
修改参数界定符
默认情况下, {% raw %}:::{% endraw %}
作为参数分界符, 可以使用
来修改
显示进度
1 2 3 4 5 6 7 8 9 10 11 12
| --bar 或 --eta 或 --progress 输出到文件 --joblog parallel --joblog /tmp/log
|
1
| seq 1000 | parallel -j30 --bar '(echo {};sleep 0.1)'
|
使用指定分割符
指定输入项是以 delim 来结束的.
替换符
{% raw %}{}{% endraw %}
默认情况下, {% raw %}{}{% endraw %}
代表输入项.
可以通过 -I
来修改.
{% raw %}{.}{% endraw %}
将输入项去掉扩展名后输出.
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ parallel --no-run-if-empty --bar -a test.file echo {} {.} 0% 0:4=0s sub.dir/bar sub.dir/bar sub.dir/bar 25% 1:3=0s sub.dir/bar sub.dir/foo.jpg sub.dir/foo 50% 2:2=0s sub.dir/bar subdir/foo.jpg subdir/foo 75% 3:1=0s sub.dir/bar foo.jpg foo 100% 4:0=0s sub.dir/bar
|
{% raw %}{/}{% endraw %}
获取输入项的文件名
{% raw %}{/.}{% endraw %}
获取输入项的文件名, 但去掉扩展名
{% raw %}{//}{% endraw %}
获取输入项的目录名
`{% raw %}
{% endraw %}`
任务的ID
{% raw %}{%}{% endraw %}
任务的 slot 数字
1 2 3 4 5
| $ parallel --no-run-if-empty -a test.file echo {#} {%} {.} 2 2 subdir/foo 1 1 foo 3 3 sub.dir/foo 4 4 sub.dir/bar
|
{% raw %}{n}{% endraw %}
输入源的第 n
个参数.
1 2 3 4
| $ parallel echo {2} ::: a b c ::: "这是第二个参数" ::: "这是第三个参数" 这是第二个参数 这是第二个参数 这是第二个参数
|
{% raw %}{n.}{% endraw %}
同 {% raw %}{n}{% endraw %}
, 只是去掉了文件扩展名
{% raw %}{n/}{% endraw %}
同 {% raw %}{/}{% endraw %}
, 只是处理第 n
个参数的情况
{% raw %}{n//}{% endraw %}
同 {% raw %}{//}{% endraw %}
, 只是处理第 n
个参数的情况
{% raw %}{n/.}{% endraw %}
同 {% raw %}{/}{% endraw %}
, 只是处理第 n
个参数的情况, 并且去掉扩展名.
限制参数长度和大小
--xargs
可以让 parallel 支持多个参数
有无 xargs 的区别
1 2 3 4 5 6
| $ parallel --xargs echo ::: a b c ::: "这是第二个参数" ::: "这是第三个参数" a 这是第二个参数 这是第三个参数 b 这是第二个参数 这是第三个参数 c 这是第二个参数 这是第三个参数 $ parallel echo ::: a b c ::: "这是第二个参数" ::: "这是第三个参数" a 这是第二个参数 这是第三个参数 b 这是第二个参数 这是第三个参数 c 这是第二个参数 这是第三个参数
|
--jobs 4
指定任务数
-N3
限制参数最大个数
处理空格
1
| --trim <n|l|r|lr|rl> Trim white space in input.
|
输出打印处理
前缀
以参数作为输出前缀
1 2 3 4 5 6 7 8 9 10 11
| $ seq 10 | parallel --tagstring "hello {} ===> " echo - hello 2 ===> 2 hello 4 ===> 4 hello 5 ===> 5 hello 6 ===> 6 hello 8 ===> 8 hello 9 ===> 9 hello 7 ===> 7 hello 3 ===> 3 hello 1 ===> 1 hello 10 ===> 10
|
把输出结果保存到文件
默认保存在 /tmp
目录中.
1 2 3 4 5 6 7 8 9 10 11 12 13
| $ seq 10 | parallel --files --tagstring "hello {} ===> " echo - hello 2 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/parZQYda.par hello 4 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/pariqW5T.par hello 3 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/parhkbu1.par hello 5 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/par4ts6Z.par hello 6 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/parK3w5V.par hello 7 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/par6UDLa.par hello 8 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/par_twoW.par hello 9 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/parPlgWZ.par hello 1 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/parjwUR0.par hello 10 ===> /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/parZoyUn.par $ cat /var/folders/lz/mpwxkp6s7rq62r08vt2h_j480000gn/T/parZQYda.par 2
|
详细保存结果到文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| $ seq 10 | parallel --results outdir --tagstring "hello {} ===> " echo - hello 2 ===> 2 hello 3 ===> 3 hello 4 ===> 4 hello 5 ===> 5 hello 6 ===> 6 hello 7 ===> 7 hello 8 ===> 8 hello 9 ===> 9 hello 1 ===> 1 hello 10 ===> 10 $ tree outdir outdir └── 1 ├── 1 │ ├── seq │ ├── stderr │ └── stdout ├── 10 │ ├── seq │ ├── stderr │ └── stdout ├── 2 │ ├── seq │ ├── stderr │ └── stdout ├── 3 │ ├── seq │ ├── stderr │ └── stdout ├── 4 │ ├── seq │ ├── stderr │ └── stdout ├── 5 │ ├── seq │ ├── stderr │ └── stdout ├── 6 │ ├── seq │ ├── stderr │ └── stdout ├── 7 │ ├── seq │ ├── stderr │ └── stdout ├── 8 │ ├── seq │ ├── stderr │ └── stdout └── 9 ├── seq ├── stderr └── stdout 11 directories, 30 files
|
控制并发数
1 2 3 4 5 6 7 8 9 10
| --jobs N 或 -j N 或 --max-procs N 或 -P N
|
如果是0, 则意味着尽可能多的并发.(每个任务在每个CPU上尽可能 100% 占用CPU)
只打印输出命令, 则不执行
交互式执行
恢复任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ parallel --joblog /tmp/log exit ::: 1 2 3 0 $ cat /tmp/log Seq Host Starttime JobRuntime Send Receive Exitval Signal Command 2 : 1514099245.436 0.013 0 0 2 0 exit 2 1 : 1514099245.432 0.019 0 0 1 0 exit 1 3 : 1514099245.442 0.012 0 0 3 0 exit 3 4 : 1514099245.448 0.011 0 0 0 0 exit 0 $ parallel --resume --joblog /tmp/log exit ::: 1 2 3 0 $ cat /tmp/log Seq Host Starttime JobRuntime Send Receive Exitval Signal Command 2 : 1514099245.436 0.013 0 0 2 0 exit 2 1 : 1514099245.432 0.019 0 0 1 0 exit 1 3 : 1514099245.442 0.012 0 0 3 0 exit 3 4 : 1514099245.448 0.011 0 0 0 0 exit 0
|
可以看到, 如果有执行过的话, --resum
则不会重新执行了. 只会执行其他还没有完成的
只重新执行失败的任务
1
| parallel --resume-failed --joblog /tmp/log exit ::: 1 2 3 0 0 0
|
限制资源占用
1 2 3 4 5 6 7 8
| parallel --load 100% parallel --noswap parallel --memfree 1G 这表示只有内存空闲大于1G时才执行任务 parallel --nice 17
|
使用远程主机来执行
如果远程主机使用的是非22端口, 则中以在 ~/.ssh/config
中配置:
1 2 3 4 5 6
| Host host1.v Port 22001 Host host2.v Port 22002 Host host3.v Port 22003
|
注意, 也要在远程主机上安装 parallel 才行.
1
| parallel -S userName@host1.v -S userName@host2.v echo ::: hello
|
例子: 将当前目录下的文件传输到远程host然后压缩(虽然无实际意义, 这只是演示用法..)
1
| ls | parallel -S userName@host1.v --transfer gzip {}
|
设置工作目录
1
| ls | parallel --sshlogin userName@host1.v --workdir /tmp/new_dir/ --transferfile {} --return {}.gz --cleanup gzip {}
|
这将会在远程主机 hot1.v
的 /tmp/new_dir/
上进行文件传输.
--cleanup
表示清理远程上的相应数据或文件.
--return {}.gz
表示返回相应的数据或文件.
--transferfile {}
表示要传输的数据或文件.
例子收集
命令在一个文件中
假设你将一个文件保存了所有要执行的命令. 例如 每行一条 curl xxxx
之类的命令.则可以这样子:
1
| cat /tmp/ad-monitor-2018-01-30_11_51_36.sh | parallel --no-run-if-empty --progress --joblog /tmp/ad-monitor-progress.log --jobs 4 > /tmp/parallel-monitor.log
|
注意, 不能像以下这样子
1
| cat /tmp/ad-monitor-2018-01-30_11_51_36.sh | parallel --no-run-if-empty --progress --joblog /tmp/ad-monitor-progress.log --jobs 4 {} > /tmp/parallel-monitor.log
|
如果在后面加 {}
的话, 则会有问题. 它会转义输出我们的命令(可以用 --dryrun
选项查看要执行的实际情况, 它只是输出要执行的命令, 而不会真正执行)
批量修改文件名后缀
将所有 bz2 后缀的文件, 变成 gz 后缀
1 2 3 4 5
| ls *.bz2 | parallel --dryrun mv {} {/.}.gz ls *.bz2 | parallel mv {} {/.}.gz
|
后台并行执行命令列表
1
| nohup parallel --no-run-if-empty --progress --joblog /tmp/ad-monitor-progress.log --jobs 2 :::: /tmp/test-parallel.sh > /tmp/parallel-monitor.log 2>&1 &
|
其中 /tmp/test-parallel.sh
的内容格式如下
1 2 3 4
| sleep 10 curl http://www.qq.com sleep 10 ecoh "hello"
|
这样子, 就可以并行执行这些命令了. 并且是在后台进程中执行.