[转帖]好用的parallel命令
https://www.cnblogs.com/codelogs/p/16060043.html
原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。
简介#
有时,我们需要处理一批数据,使用while循环是个不错的想法,但while循环中的命令是一个一个执行的,如果要批量处理的数据很多,执行时间就会很长,而parallel可以让命令并行执行,从而缩短命令执行时间。
下面,我们先用ncat来模拟一个处理数据的接口。
模拟接口#
ncat -lk 8088 -c 'sleep 1;printf "HTTP/1.1 200 OK\r\nContent-Type: plain/text\r\nContent-Length: 3\r\n\r\nok\n"'
此接口直接睡眠1秒,然后返回一个ok,表示数据处理成功。
调用接口#
curl -X POST http://localhost:8088/user/add -d '{"user_id": 1, "user_name":"u1"}'
测试数据#
假设有10条数据,在data.txt中,如下:
1 u1
2 u2
3 u3
...
使用while循环处理#
$ time while read -r -a line; do
curl -X POST http://localhost:8088/user/add -d '{"user_id": '${line[0]}', "user_name":"'${line[1]}'"}'
done < data.txt
ok
ok
ok
ok
ok
ok
ok
ok
ok
ok
real 0m10.276s
user 0m0.094s
sys 0m0.096s
使用while循环处理,其中time命令用来计时,real表示while命令的执行时间,可以看到,处理完10条数据花了约10秒,接下来我们使用parallel并发执行。
使用parallel并发执行#
$ time cat data.txt | parallel -j10 -C '\s+' curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {1}, \"user_name\":\"{2}\"}\'
ok
ok
ok
ok
ok
ok
ok
ok
ok
ok
real 0m1.205s
user 0m0.203s
sys 0m0.060s
使用parallel命令并发执行curl,-j10表示最多10个并发进程,-C '\s+' 表示使用空白来拆分每行(注:\s+是表示空白的正则表达式),这样就可以使用{1}表示第1列,{2}表示第2列了,如我们所预期的,10条数据使用10个并发,处理完约1秒。
有用的--tag选项#
上例的接口很简单,直接返回ok,但在有大量数据需要处理时,有可能出现部分数据处理失败,像上面的执行结果中,就很难知道是哪些数据处理失败了,还好parallel提供了--tag选项,可以将处理的数据与执行结果都打印出来,如下:
$ cat data.txt | parallel -j10 -C '\s+' --tag curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {1}, \"user_name\":\"{2}\"}\'
1 u1 ok
2 u2 ok
4 u4 ok
3 u3 ok
5 u5 ok
6 u6 ok
7 u7 ok
8 u8 ok
9 u9 ok
10 u10 ok
这样,什么数据执行对应什么结果,就一目了然了。
查看进度#
如果有大量数据需要处理,处理时能直观的看到一个进度就再好不过了,parallel提供了3个查看进度的选项,--bar、--progress和--eta,一般使用--bar、--progress即可。
其中--bar适合待处理数据量确定的场景,因为parallel需要读取所有数据后才能根据数据总量计算进度条。
而--progress适合待处理数据量未知的场景,只能看到已经处理了多少条数据,如下:
# 使用 --bar 显示进度条
cat data.txt | parallel -j10 -C '\s+' --tag --bar curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {1}, \"user_name\":\"{2}\"}\'
# 使用 --progress 显示处理条数
cat data.txt | parallel -j10 -C '\s+' --tag --progress curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {1}, \"user_name\":\"{2}\"}\'
--joblog与--resume-failed选项#
相信当你使用脚本处理有一定数据量的数据时,一定会遇到数据偶尔处理失败的情况(由于网络不稳定),这时你需要将处理失败的数据再次找出来,然后再次处理,过程还是挺麻烦的。
好在parallel命令已经考虑到了这种场景,并提供了--joblog与--resume-failed选项,当有失败产生时,你只需要再次执行整个命令行即可。
# 模拟接口修改如下,使得接口有概率失败,成功返回true,失败返回fail
ncat -lk 8088 -c 'sleep 1;r=$(head /dev/urandom | tr -dc 0-9 | head -c 1);printf "HTTP/1.1 200 OK\r\nContent-Type: plain/text\r\nContent-Length: 5\r\n\r\n";[ $r -lt 5 ] && printf "true\n" || printf "fail\n"'
# parallel添加--joblog job.log --resume-failed参数,这次我们将处理脚本封装为一个函数,并用export -f使其生效,这样就可以在parallel中直接使用函数了
function deal_data(){
res=$(curl -s -X POST http://localhost:8088/user/add -d '{"user_id": '$1', "user_name":"'$2'"}')
echo "$res"
[[ "$res" == "true" ]] && return 0 || return 1
}
export -f deal_data
$ cat data.txt | parallel -j10 -C '\s+' --tag --joblog job.log --resume-failed deal_data
1 u1 true
2 u2 true
4 u4 true
5 u5 true
3 u3 fail
6 u6 true
8 u8 true
7 u7 true
9 u9 true
10 u10 fail
# 上面有2条数据处理失败,我们再次执行以上命令,如下,可以看到本次只执行了之前失败的2条数据,perfect!
$ cat data.txt | parallel -j10 -C '\s+' --tag --joblog job.log --resume-failed deal_data
3 u3 true
10 u10 true
--semaphore选项#
parallel既然提供了并发,那么必然会遇到并发冲突问题,比如sed命令就不支持并发的修改同一文件,不过parallel已经提供了--semaphore选项来解决这个问题了。
如下,其中sem是parallel --semaphore的别名,与其是等价的。
function deal_data(){
res=$(curl -s -X POST http://localhost:8088/user/add -d '{"user_id": '$1', "user_name":"'$2'"}')
echo "$res"
[[ "$res" == "true" ]] && return 0 || return 1
}
export -f deal_data
$ grep -vnP 'ok$' data.txt |parallel -C ':|\s+' --tag 'deal_data {2} {3}; [[ $? -eq 0 ]] && sem -j1 sed -i \"{1} s/$/ ok/\" data.txt'
这里的逻辑是,每处理成功data.txt中的一条数据,就使用sed将data.txt中的那行数据末尾加一个ok,表示执行成功,然后在前面使用grep找不包含ok的数据,就达到了命令每次都处理未处理或处理失败数据的逻辑。而sem -j1保护了sed,避免sed命令并发执行。
与mysql结合使用#
parallel还可以和mysql结合使用,将任务导入mysql中或是执行mysql中的任务,如下:
# 1.将任务数据导入到pardb库的paralleljobs表中,pardb库需要事先自行创建
cat data.txt |parallel --sqlmaster 'sql:mysql://user:pass@localhost:3306/pardb/paralleljobs'
# 2.执行paralleljobs表中待处理任务,Exitval=-1000为待处理任务
function deal_data(){
p=($*)
res=$(curl -s -X POST http://localhost:8088/user/add -d '{"user_id": '${p[0]}', "user_name":"'${p[1]}'"}')
echo "$res"
[[ "$res" == "true" ]] && return 0 || return 1
}
export -f deal_data
parallel --sqlworker 'sql:mysql://user:pass@localhost:3306/pardb/paralleljobs' --tag deal_data
处理csv数据#
parallel命令还能很方便的处理csv文件数据,比如将data.txt改为data.csv,如下:
$ cat data.csv
user_id,user_name
1,u1
2,u2
3,u3
...
# 使用--header : 选项来读取csv的表头,然后就可以{user_id},{user_name}来占位命令参数了
$ cat data.csv | parallel --header : -C ',' --tag curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {user_id}, \"user_name\":\"{user_name}\"}\'
--pipe选项#
有很多文本处理命令,并不从参数中获取数据,而是从标准输入中获取,比如paste,通过指定--pipe选项,能将数据传入到待执行命令的输入流中去。
# 比如我想把data.csv变成data.json,且每3条数据聚合成一个json数组,如下:
$ cat data.csv | parallel --header : -C ',' echo \'{\"user_id\": {user_id}, \"user_name\":\"{user_name}\"}\' | parallel -N3 --pipe paste -s -d, | sed -e 's/^/\[/' -e 's/$/]/'
[{"user_id": 7, "user_name":"u7"},{"user_id": 8, "user_name":"u8"},{"user_id": 9, "user_name":"u9"}]
[{"user_id": 1, "user_name":"u1"},{"user_id": 2, "user_name":"u2"},{"user_id": 3, "user_name":"u3"}]
[{"user_id": 4, "user_name":"u4"},{"user_id": 5, "user_name":"u5"},{"user_id": 6, "user_name":"u6"}]
[{"user_id": 10, "user_name":"u10"}]
第一个parallel将每条数据变成了{"user_id": 1, "user_name":"u1"}形式。
第二个parallel将每3个json传给paste的输入流,然后paste使用逗号将它们连接起来。
每三个sed给首尾加上[],即成为了需要的数据格式。
与tmux结合使用#
parallel提供了--tmuxpane,使得可以实现在tmux的多个panel中执行命令,这非常适合用来观察一些监控命令的结果,比如查看每台主机的网络情况。
# 使用ping同时监控简书、百度、知乎的网络情况,注意,必须要加--delay选项
$ printf "www.jianshu.com\nwww.jianshu.com\nwww.baidu.com\nwww.zhihu.com"|parallel -j0 --delay 1 --tmuxpane ping {0}
See output with: tmux -S /tmp/tmsOHGXM attach
# 查看tmux面板
$ tmux -S /tmp/tmsOHGXM attach
如下,为tmux面板的内容,你将能直观的看到4台机器的ping实时结果。
总结#
如果你经常使用shell来帮助你处理各种问题,我想parallel命令就非常适合你,它真的太强大太方便了。
往期内容#
[转帖]好用的parallel命令的更多相关文章
- [转帖]EXPDP dumpfile和parallel的关系
http://blog.itpub.net/28602568/viewspace-2133375/ 转帖 EXPDP 里面 parallel 与 dumpfile 里面的文件数的关系. 但是我这里有一 ...
- 【转帖】Linux定时任务Crontab命令详解
Linux定时任务Crontab命令详解 https://www.cnblogs.com/intval/p/5763929.html 知道有crontab 以及 at 命令 改天仔细学习一下 讲sys ...
- [转帖]linux下安装7z命令及7z命令的使用
linux下安装7z命令及7z命令的使用 https://www.cnblogs.com/yiwd/p/3649094.html yum install p7zip 执行命令为 7za x 或者是 7 ...
- [转帖]Linux系列之SAR命令使用详解
Linux系列之SAR命令使用详解 sar是System Activity Reporter(系统活动情况报告)的缩写.这个工具所需要的负载很小,也是目前linux中最为全面的性能分析工具之一.此款工 ...
- [转帖]持久化journalctl日志清空命令查看配置参数详解
持久化journalctl日志清空命令查看配置参数详解 最近 linux上面部署服务 习惯使用systemd 进行处理 这样最大的好处能够 使用journalctl 进行查看日志信息. 今天清理了下 ...
- [转帖]XCopy复制文件夹命令及参数详解以及xcopy拷贝目录并排除特定文件
XCopy复制文件夹命令及参数详解以及xcopy拷贝目录并排除特定文件 https://www.cnblogs.com/smartsmile/p/7665979.html xcopy dirA dir ...
- [转帖]Docker学习之Dockerfile命令详解
Docker学习之Dockerfile命令详解 https://it.baiked.com/system/docker/2436.html 图挺好的 前言 之前,制作镜像的伪姿势搭建已经见过了,今天介 ...
- [转帖]Windows与Linux的命令行命令对比
Windows与Linux的命令行命令对比 https://www.cnblogs.com/sztom/p/10785140.html * Windows不区分大小写,Linux区分大小写的. sn ...
- 分享一个linux环境下快速读取行数的命令
最初是因为我需要计算一天的日志行数,如果用传统意义上的cat a.log |wc -l的话因为是单线程,所以需要计算半小时的样子,后来同组的小伙伴教了我一个方法可以有效提高计算速度,将计算时间减半. ...
- PLSQL_性能优化系列03_Oracle Parallel并发处理
2014-09-25 Created By BaoXinjian
随机推荐
- 实时入库不用愁,HStore帮分忧
本文分享自华为云社区<直播回顾 | 实时入库不用愁,HStore帮分忧>,作者:汀丶. 海量数据时代,如何实现数据实时入库与实时查询?GaussDB(DWS) HStore表为数据高效存储 ...
- CloudIDE插件在手,按时下班不愁
摘要:带你通过插件机制将CloudIDE扩展出你想要的功能,在CloudIDE中看视频,玩游戏,聊天都可以通过我们的插件来轻松实现,让生产工具不再枯燥,开发工作多姿多彩. 距离华为云CloudIDE在 ...
- 【万字干货】OpenMetric与时序数据库存储模型分析
摘要:解读OpenMetric规范和指标的模型定义基础上,结合当下主流的时序数据库核心存储及处理技术,尝试让用户(架构师.开发者或使用者)结合自身业务场景选择合适的产品,消除技术选型的困惑. 本文分享 ...
- 解读clickhouse存算分离在华为云实践
摘要:本文是我们对clickhouse做了最简单的支持obs的适配改造. 本文分享自华为云社区<clickhouse存算分离在华为云实践>,作者: he lifu. clickhouse是 ...
- Solon2 开发之IoC,四、注入依赖与初始化
Solon 强调 有克制的注入 + 手动控制 结合的模式.好处是,代码用料少.启动快. Bean 的关键生命节点: 节点 说明 1. Constructor(构造方法) 不支持参数注入 2. @Inj ...
- Axure Axhub Charts 数据编辑、显示
Axhub Charts图表元件库: https://www.axureshop.com/a/100749.html
- 师爷,翻译翻译什么叫AOP
张麻子:汤师爷,翻译翻译,什么叫AOP? 汤师爷:这还用翻译. 张麻子:我让你翻译给我听,什么叫AOP? 汤师爷:不用翻译,切面编程就是AOP啊. 黄四郎:难道你听不懂什么叫AOP? 张麻子:我就想让 ...
- 【iOS源码混淆工具】iOS代码混淆工具
主要功能 Ipa Guard是一款功能强大的ipa混淆工具,不需要ios app源码,直接对ipa文件进行混淆加密.可对IOS ipa 文件的代码,代码库,资源文件等进行混淆保护. 可以根据设置对函数 ...
- iOS安全加固探讨:代码混淆、类名方法名混淆等方法
摘要:本文探讨了iOS平台下的安全保护,以及几种常见的加固方法,包括字符串加密.类名方法名混淆.程序代码混淆和加入安全SDK等.通过这些方法,我们可以有效地提高iOS应用的安全性. 引言: 随着智能手 ...
- 5、SpringBoot连接数据库引入mybatis
系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...