今天从运维同学,云平台同学那里学了一点AWK,离全栈工程师,DEVOPS又近了历史性的一步。
需求是这样的,在性能测试之后,要在访问日志里滤出所有大于100毫秒的慢调用记录,日志长下面的样子,调用耗时在最后一列:
[2015-08-20 00:00:55.600] - [192.168.0.73 /192.168.0.73:56292 /192.168.0.75:1080 32379 com.vip.infrastructure.xxx.MyService_2.0.0 0 106046 100346 90ms 110ms]
最后最后收工时的写法很简单:
time sed "s|ms]||g" access.*.log | awk '{if($(NF) > 100) print}'
real 1m11s<br /> user 1m5s<br /> sys 1m8s<br />
先用sed过滤掉"ms]”,然后用awk按空格分列,对最后一列进行阀值判断,命中则输出整条日志。
12G日志耗时共1分11秒,平均每秒处理200M的数据,考虑到SSD盘的IO速度,比较满意了。
但,只是这么简单的一行,得出来的过程其实也是很复杂的。
比如,一不小心就成了 一个Linux老梗 的主角,傻傻的用cat去打开文件,多花了10秒。
cat access.*.log | sed "s|ms]||g" | awk ' {if($(NF) > 100) print}'
又比如,尝试单纯用awk,减少一条管道,但结果反而慢了三十多秒。
awk '{gsub("ms]","",$NF); if( $(NF)>100 ) print }' access.*.log
又比如,用上了 mawk ,号称最快的awk,再运行上面的语句快了二十秒,但还是比sed+awk慢了十秒,而且sed+awk的场景里把awk换成mawk,并没有什么变化。
最后,还尝试了 parallel ,发现要不和原来差不多,要不更慢了,比如下面这条居然跑了4分钟,而且还要写一堆反斜杠:
time sed "s|ms]||g" osp_access.*.log | parallel --pipe mawk /'/{if /($/(NF/) />100/) print}/'
折腾是乐趣。