parallel -d ' ' --jobs 5 --timeout 180 --joblog /var/log/parallel.job 'echo {} $(date "+\%Y\%m\%d \%H:\%M:\%S");rsync -Cauvz
/root/$(date +\%Y\%m\%d).txt {}:/root/$(date +\%Y\%m\%d)/$(date +\%Y\%m\%d)/'-d '': 作业分隔符为一个空格
--jobs 5: 同时运行5个任务
--timeout 180: 任何一个运行超过180秒,则结束任务
--joblog /var/log/parallel.job: 所有任务的日志文件路径和名称为 /var/log/parallel.job。所有任务的输出将被记录在这个文件中
rsync 命令,用于同步文件。-C 表示以压缩模式运行,-a 表示归档模式,-u 表示只更新较新的文件,-v 表示详细模式,-z 表示压缩文件数据日志类型:
Seq Host Starttime JobRuntime Send Receive Exitval Signal Command#######parallel --jobs 4 --joblog /tmp/text123.log 'ping -c 1 {}' :::: ipparallel --jobs 4 --joblog /tmp/text123.log 'echo {} $(date "+\%Y\%m\%d \%H:\%M:\%S"); ping -c 1 {}' :::: ipparallel --timeout 10 --jobs 4 --joblog /tmp/text123.log 'echo {} $(date "+\%Y\%m\%d \%H:\%M:\%S"); ping {}' :::: iphttps://www.jianshu.com/p/cc54a72616a1一. paralle
parallel 是一个强大的命令行工具,用于在多个CPU核心上并行执行多个任务。它允许你同时运行多个命令或脚本,从而可以显著提高处理速度此命令用于并行执行另一个命令,(顺序执行,打印到日志顺序是执行任务完成的顺序)。Usage:parallel [options] [command [arguments]] < list_of_arguments
parallel [options] [command [arguments]] (::: arguments|:::: argfile(s))...
cat ... | parallel --pipe [options] [command [arguments]]常用选项:
::: 后面接参数
:::: 后面接文件
-j、--jobs 并行任务数
-N 每次输入的参数数量
--xargs会在一行中输入尽可能多的参数
-xapply 从每一个源获取一个参数(或文件一行)
--header 把每一行输入中的第一个值做为参数名
-m 表示每个job不重复输出“背景”(context)
-X 与-m相反,会重复输出“背景文本”
-q 保护后面的命令
--trim lr 去除参数两头的空格,只能去除空格,换行符和tab都不能去除
--keep-order/-k 强制使输出与参数保持顺序 --keep-order/-k
--tmpdir/ --results 都是保存文件,但是后者可以有结构的保存
--delay 延迟每个任务启动时间
--halt 终止任务
--pipe 该参数使得我们可以将输入(stdin)分为多块(block)
--block 参数可以指定每块的大小
--timeout 指定等待时间避免无谓的等待1.并行执行简单的命令
seq 1 10 | parallel echo {1}2.使用变量
seq 1 10 | parallel 'echo {} times two is {1} * 2'3.并行执行脚本
seq 1 10 | parallel ./myscript.sh4.限制并行任务的数量
seq 1 100 | parallel -j5 echo {1}1. 把文件的每一行作为单独的输出
cat a.txt | parallel echo2. 从 cat 输出的每一行中提取第一个字段
cat a.txt | parallel echo {1}3. -E 参数指定一个值做为结束标志
parallel -E stop echo ::: A B C D E stop C 1 2 12 D4.--no-run-if-empty 来跳过空行cat a.txt | parallel --no-run-if-empty echo5. 构建命令行
如果parallel之后没有给定命令,那么这些参数会被当做命令
parallel ::: ls "cat a.txt" pwd6.替换字符串
Parallel支持多种替换字符串,默认使用 {},使用 -I 改变替换字符串符号 {}。其最常见的字符串替换包括以下几种:{.},去掉扩展名;{/},去掉路径,只保留文件名;{//},只保留路径;{/.},同时去掉路径和扩展名;{#},输出任务编号。同时对于每一个字符串替换都可以自己指定符号:-I对应{};--extensionreplace替换 {.};--basenamereplace替换 {/};--dirnamereplace替换{//};--basenameextensionreplace替换 {/.};--seqreplace替换 {#}parallel echo ::: A/B.C ; parallel echo {} ::: A/B.C ; parallel -I ,, echo ,, ::: A/B.C
去掉扩展名
parallel echo {.} ::: A/B.C
parallel --extensionreplace ,, echo ,, ::: A/B.C
去除路径
parallel echo {/} ::: A/B.C ; parallel --basenamereplace ,, echo ,, ::: A/B.C
只保留路径
parallel echo {//} ::: A/B.C ; parallel --dirnamereplace ,, echo ,, ::: A/B.C
同时去掉路径和扩展名
parallel echo {/.} ::: A/B.C ; parallel --basenameextensionreplace ,, echo ,, ::: A/B.C
输出任务编号。同时对于每一个字符串替换都可以自己指定符号
parallel echo {#} ::: A B C ; parallel --seqreplace ,, echo ,, ::: A B C如果有多个输入源时,可以通过 {编号} 指定某一个输入源的参数
parallel --xapply echo {1} and {2} ::: A B ::: C D
# 可以使用 / // /. 和 . 改变指定替换字符串
parallel echo /={1/} //={1//} /.={1/.} .={1.} ::: A/B.C D/E.F
# 位置可以是负数,表示倒着数
parallel echo 1={1} 2={2} 3={3} -1={-1} -2={-2} -3={-3} ::: A B ::: C D ::: E F7.按列输入和指定参数名
使用 --header 把每一行输入中的第一个值做为参数名
parallel --xapply --header : echo f1={f1} f2={f2} ::: f1 A B ::: f2 C D | tee d.txtperl -e 'printf "f1\tf2\nA\tB\nC\tD\n"' > tsv-file.tsv
parallel --header : --colsep '\t' echo f1={f1} f2={f2} ::: tsv.txt8.多参数
--xargs会在一行中输入尽可能多的参数(与参数字符串长度有关),通过-s可指定一行中参数的上限
parallel --jobs 4 echo pre-{}-post ::: A B C D E F G
-m参数表示每个job不重复输出“背景”(context),-X则与-m相反,会重复输出“背景文本”
parallel --jobs 2 -m echo pre-{}-post ::: A B C D E F G
parallel --jobs 2 -X echo pre-{}-post ::: A B C D E F G-N 限制每行参数的个数,其中-N0表示一次只读取一个参数,且不输入这个参数(作为计数器来使用)。9.引用10.去除空格
使用--trim去除参数两头的空格
parallel --trim r echo pre-{}-post ::: ' A '
parallel --trim l echo pre-{}-post ::: ' A '
parallel --trim lr echo pre-{}-post ::: ' A '11.控制输出
使用--tag以参数做为输出前缀,使用--tagstring修改输出前缀
parallel --tag echo foo-{} ::: A B C
parallel --tagstring {}-bar echo foo-{} ::: A B C--dryrun作用类似于echoparallel --dryrun echo123 {} ::: A B C--verbose则在运行之前先打印命令
parallel --verbose echo {} ::: A B CParallel 会延迟输出,直到一组命令执行完成。使用--ungroup,可立刻打印输出已完成部分
parallel -j2 --ungroup 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1使用 --ungroup 会很快,但会导致输出错乱,一个任务的行输出可能会被另一个任务的输出截断。像上例所示,第二行输出混合了两个任务: '4-middle' '2-start'。使用 --linebuffer避免这个问题(稍慢一点)
parallel -j2 -k ' printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1强制使输出与参数保持顺序 --keep-order/-k
parallel -j2 -k 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 112.将输出保存到文件
Parallel可以把每一个任务的输出保存到文件中,临时文件默认保存在 /tmp 中,可以使用 --tmpdir改变(或者修改 $TMPDIR):
parallel --files ::: A B C
parallel --tmpdir ~ --files ::: A B C
TMPDIR=~ parallel --files ::: A B C输出文件可以有结构的保存 --results,输出文件不仅包含标准输出(stdout)也会包含标准错误输出(stderr)
parallel --results outdir echo ::: A B C
tree outdir使用多个变量的时候会显示很有用
parallel --header : --results outdir echo ::: f1 A B ::: f2 C D
tree outdir13.控制执行
使用64个任务执行128个休眠命令
time parallel -N0 -j64 sleep 1 ::: {1..128}
每个cpu两个任务
time parallel -N0 --jobs 200% sleep 1 ::: {1..128}使用 --jobs 0 表示执行尽可能多的并行任务
time parallel -N0 --jobs 0 sleep 1 ::: {1..128}除了基于cpu使用率之外,也可以基于cpu数
time parallel --use-cpus-instead-of-cores -N0 sleep 1 ::: {1..128}14.交互
通过使用 --interactive 在一个任务执行之前让用户决定是否执行parallel --interactive echo ::: 1 2 315.耗时
当job有大量的IO操作时,为避免“惊群效应”,可使用--delay参数指定各个job开始的时间间隔
parallel --delay 2.5 echo Starting {}\;date ::: 1 2 3若已知任务超过一定时间未反应则为失败则可以通过--timeout指定等待时间避免无谓的等待。GNU parallel能计算所有任务运行时间的中位数,因此可以指定时间为中位数的倍数关系。
parallel --timeout 4.1 sleep {}\; echo {} ::: 2 4 6 8
parallel --timeout 200% sleep {}\; echo {} ::: 2.1 2.2 3 7 2.316.显示任务进度信息
parallel有多种方式可用来动态的显示任务进度信息
parallel --eta sleep ::: 1 3 2 2 1 3 3 2 1
parallel --progress sleep ::: 1 3 2 2 1 3 3 2 1使用--joblog参数能够生成各个任务的日志文件
parallel --joblog /tmp/log exit ::: 1 2 3 0
cat /tmp/log通过--resume-failed参数可以重新运行失败的任务; --retry-failed的作用与--resume-failed类似,只是--resume-failed从命令行读取失败任务,而--retry-failed则是从日志文件中读取失败任务
parallel --resume-failed --joblog /tmp/log exit ::: 1 2 3 0 0 0
cat /tmp/logparallel --retry-failed --joblog /tmp/log
cat /tmp/log17.终止任务
parallel支持在某一情况下(如第一个失败或成功时,或者20%任务失败时)终止任务,终止任务又有两种类型,其一为立即终止(通过--halt now指定),杀死所有正在运行的任务并停止生成新的任务,其二为稍后终止(通过--halt soon指定),停止生成新任务并等待正在运行任务完成
parallel -j2 --halt soon,fail=1 echo {}\; exit {} ::: 0 0 1 2 3
parallel -j2 --halt soon,fail=20% echo {}\; exit {} ::: 0 1 2 3 4 5 6 7 8 9
parallel -j2 --halt now,success=1 echo {}\; exit {} ::: 1 2 3 0 4 5 6parallel还支持在任务失败后重试运行--retries
parallel -k --retries 3 'echo tried {} >>/tmp/runs; echo completed {}; exit {}' ::: 1 2 0
cat /tmp/runs 18.资源限制
parallel能够在开始一个新的任务前检查系统的负载情况防止过载(通过--load可指定负载),同时还能检查系统是否使用了交换空间(swap)(通过--noswap限制使用swap)
parallel --load 100% echo load is less than {} job per cpu ::: 1
parallel --noswap echo the system is not swapping ::: now对于某些占用内存较多的程序,parallel会检查内存只有内存满足时才启动任务(通过--memfree指定需要内存大小),而且在启动任务后内存不够50%时会杀掉最新开始的任务,直到这个任务完成再重新开始那些杀死的任务
parallel --memfree 1G echo will run if more than 1 GB is ::: free
还可以通过--nice来指定任务的优先级
parallel --nice 17 echo this is being run with nice -n ::: 1719.远程操作
可使用-S host来进行远程登陆parallel -S username@$SERVER1 echo running on ::: username@$SERVER120.文件传输
parallel 文件传输使用的是rsync
echo This is input_file > input_file
parallel -S $SERVER1 --transferfile {} cat ::: input_file21.--pipe
--pipe参数使得我们可以将输入(stdin)分为多块(block),然后分配给多个任务多个cpu以达到负载均衡,最后的结果顺序与原始顺序一致。使用--block参数可以指定每块的大小,默认为1M
perl -e 'for(1..1000000){print "$_\n"}' > num1000000
cat num1000000 | parallel --pipe wc如果不关心结果顺序,只想要快速的得到结果,可使用--round-robin参数。没有这个参数时每块文件都会启动一个命令,使用这个参数后会将这些文件块分配给job数任务(通过--jobs进行指定)。若想分配更为均匀还可同时指定--block参数cat num1000000 | parallel --pipe -j4 --round-robin wc
cat num1000000 | parallel --pipe -j4 --block 2M --round-robin wc二. tee
tee 是一个在 Unix 和类 Unix 系统中常用的命令行工具,它用于读取标准输入(stdin)的数据,并将其复制到标准输出(stdout)和文件中。简单来说,tee 命令可以让你同时在终端显示输出,并将其写入到一个或多个文件。-a 或 --append:将输出追加到文件末尾,而不是覆盖文件。这个参数可以写入日志文件###################################
应用
###################################
0,15 8 * * 1-5 echo -n "test1 test2 test3 test3" | parallel -d ' ' --jobs 5 --timeout 180 --joblog /var/log/parallel.job 'echo {} $(date "+\%Y\%m\%d \%H:\%M:\%S");rsync -rtlvz /root/ {}:/root/' >> /var/log/rsync.log 2>&1;
ERROR=$(awk '{ if (NR > 1 && $7 !=0) {print $10}}' /var/log/parallel.job | xargs -I {} echo -n _{}); curl $NOTIFY/${ERROR:1}echo -n 命令输出一系列服务器名称,不换行。
parallel 命令用于并行执行多个任务。
-d ' ' 指定输入字段的分隔符为空白字符。
--jobs 5 指定同时运行的最大任务数为5。
--timeout 180 设置任务的超时时间为180秒。
--joblog /var/log/parallel.job 将任务执行的日志记录到指定文件。使用 awk 命令从日志文件中提取错误信息。
xargs -I {} echo -n _{} 用于构建一个由下划线和错误信息组成的字符串-I {}: 指定替换字符串awk '{ if (NR > 1 && $7 !=0) {print $10}}' Log/bbcData.job{}: 表示 awk 的动作部分,即当满足条件时要执行的命令。
if (NR > 1 && $7 != 0): 这是一个条件语句,NR 是 awk 的内置变量,代表当前处理的是第几行。
$7 表示当前行的第7个字段(列)。条件检查是否是第二行或之后(NR > 1),并且第7个字段的值不为0($7 != 0)。
print $10: 如果上面的条件为真,则打印当前行的第10个字段。${ERROR:1} 去除变量ERROR的第一个字符########################
命令之间留空格,分号分开多个命令
parallel --jobs 5 --timeout 180 --joblog /root/nginx/log.log 'echo -n {}; echo {}' ::: a b c d e f g不加-d''把'a b c d e f g'当成一个参数
echo 'a b c d e f g' | parallel --jobs 5 --timeout 180 --joblog /root/nginx/log.log 'echo -n {}; echo {}'
加-d''把'a b c d e f g'每一个当成一个参数
echo -n 'a b c d e f g' | parallel -d' ' --jobs 5 --timeout 180 --joblog /root/nginx/log.log 'echo -n {}; echo {}'echo -n 'a b c d e f g' | parallel -d' ' --jobs 5 --timeout 180 --joblog /root/nginx/log.log 'echo -n {} >> /root/nginx/log.log; echo {} >> /root/nginx/log.log'
echo -n 'a b c d e f g' | parallel -d' ' --jobs 5 --timeout 180 --joblog /root/nginx/log.log 'echo -n {}' ; echo {} ' >> /root/nginx/log.logxargs -I {} echo -n _{}
echo "a" | xargs -I {} echo -n _{}txt=$(awk '{ if (NR > 1 && $7 ==0) {print $11}}' /root/nginx/log.log)
echo $txt txt=$(awk '{ if (NR > 1 && $7 ==0) {print $11}}' /root/nginx/log.log | xargs -I {} echo -n _{})echo -n 'a b c d e f g' | parallel -d' ' --jobs 5 --timeout 180 --joblog /root/nginx/log.log 'echo -n {}; echo {} ' >> /root/nginx/log.log;