前言
shell下经常需要处理数据,需要计算均值和标准差,最近在分析EXT4的r_await的分布情况,需要计算下在一定的读写模式下,块设备的读延迟分布。 这已不是第一次有类似的需求了,每次都要awk写一坨处理脚本,感觉不爽。
其实我要的东西比较简单, 就是读取多笔记录,通过管道传递给一个工具,该工具就可以将指定字段的均值和标准差计算出来。
...
sdb 0.00 0.00 21.00 93.00 4.02 22.88 483.23 0.31 2.70 9.52 1.16 0.88 10.00
sdb 0.00 0.00 56.00 64.00 12.03 16.00 478.40 1.91 15.90 32.57 1.31 3.67 44.00
sdb 0.00 0.00 55.00 100.00 12.03 25.00 489.24 0.78 5.01 11.42 1.48 1.45 22.40
sdb 0.00 0.00 20.00 87.00 4.02 21.52 488.75 0.34 3.18 11.40 1.29 0.86 9.20
sdb 0.00 166.00 34.00 4.00 8.01 0.66 467.37 0.22 5.79 6.47 0.00 1.58 6.00
sdb 0.00 0.00 42.00 176.00 8.04 35.61 410.06 0.55 2.51 10.67 0.57 0.70 15.20
sdb 0.00 0.00 22.00 128.00 4.02 32.00 491.84 0.50 3.07 13.09 1.34 1.07 16.00
sdb 0.00 0.00 21.00 68.00 4.02 17.00 483.69 0.51 5.89 20.38 1.41 1.26 11.20
sdb 0.00 0.00 36.00 64.00 8.02 16.00 491.84 0.49 4.92 10.56 1.75 1.20 12.00
sdb 0.00 191.00 26.00 424.00 5.02 18.24 105.87 1.63 3.40 25.23 2.07 1.29 58.00
sdb 0.00 0.00 30.00 9.00 7.01 2.25 486.15 0.32 9.23 11.33 2.22 1.64 6.40
sdb 0.00 0.00 5.00 173.00 0.02 42.75 492.05 1.06 6.04 176.80 1.11 3.53 62.80
sdb 0.00 0.00 37.00 4.00 8.02 1.00 450.37 0.38 9.17 10.16 0.00 2.34 9.60
sdb 0.00 0.00 36.00 97.00 8.02 16.12 371.73 0.60 4.51 11.56 1.90 0.84 11.20
sdb 0.00 163.00 0.00 155.00 0.00 38.40 507.41 0.05 0.34 0.00 0.34 0.03 0.40
sdb 0.00 0.00 55.00 126.00 12.03 31.25 489.72 0.72 3.98 11.27 0.79 1.06 19.20
sdb 0.00 0.00 34.00 0.00 8.01 0.00 482.35 0.39 11.41 11.41 0.00 2.12 7.20
sdb 0.00 0.00 19.00 84.00 4.01 21.00 497.32 0.28 2.72 12.84 0.43 0.58 6.00
sdb 0.00 0.00 54.00 112.00 12.02 28.00 493.78 1.52 9.16 26.96 0.57 1.71 28.40
...
上述内容是iostat -mx /dev/sd[bc] 1观察一段时间的输出,其中grep sdb 的部分,我关心的内容是第11列,即r_await的均值和方差。
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
一直用awk处理,但是总觉的不方便,不能随心所欲,下一次还的写awk,本来想自己写一个tool来计算均值和方差,但是今天搜了一下,发现了宝贝 datamash,这个工具是GNU的,Linux和Mac都有这个工具
datamash 安装
安装的话,可以源码安装,也可以apt安装:
wget http://ftp.gnu.org/gnu/datamash/datamash-1.1.0.tar.gz
tar -xzf datamash-1.1.0.tar.gz
cd datamash-1.1.0
./configure
make
make check
sudo make install
wget http://files.housegordon.org/datamash/bin/datamash_1.0.6-1_amd64.deb
sudo dpkg -i datamash_1.0.6-1_amd64.deb
本来应该是apt-get install datamash,但是好像源里面没有这个包,Mac比较简单,
brew install datamash
datamash使用
还是我们的例子,有了这个工具,我们就可以计算均值和方差了:
root@node4:~/bean# grep sdb n_186.80 | datamash -W mean 11 sstdev 11
20.843 30.743196441241
注意啊,一个或者多个空格,如果需要被当成单个空格来对待,就必须加上-W选项,我开始也吃了这个亏,如下:
root@node4:~/bean# grep sdb n_186.80 |awk '{print $11}' |datamash mean 1 sstdev 1
20.843 30.743196441241
root@node4:~/bean# grep sdb n_186.80 |datamash mean 11 sstdev 11
datamash: invalid numeric input in line 1 field 11: ''
root@node4:~/bean#
之所以报这个错误,就是因为没有-W选项,导致多个空格并没有当成一个独立的分隔符。
当然了,可以通过 -t选项来指定分隔符。
printf '1,10,,100\n' | datamash -t, sum 4
100
事实上,datamash的能力远不止于此,我们都用过数据库,知道SQL中有group by的功能,datamash 也有类似 的功能:
$ cat scores.txt
Name Subject Score
Bryan Arts 68
Isaiah Arts 80
Gabriel Health-Medicine 100
Tysza Business 92
Zackery Engineering 54
...
注意第二列是科目名称,我们可以计算不同科目的平均分和标准差:
$ datamash --sort --headers --group 2 mean 3 sstdev 3 < scores.txt
GroupBy(Subject) mean(Score) sstdev(Score)
Arts 68.9474 10.4215
Business 87.3636 5.18214
Engineering 66.5385 19.8814
Health-Medicine 90.6154 9.22441
Life-Sciences 55.3333 20.606
Social-Sciences 60.2667 17.2273
出了均值和标准差,还可获取最大最小
-
sum sum the of values
-
min minimum value
-
max maximum value
-
absmin minimum of the absolute values
-
absmax maximum of the absolute values
更多高阶的用法就参考官方文档吧