RRDTool 入门攻略(三)

获取 RRD  文件的信息

**********************************************************************************************************************
注 :该教程参考了如下内容 :
A
)官方文档 :http://oss.oetiker.ch/rrdtool/doc/index.en.html
B
abel  兄的大作 :http://bbs.chinaunix.net/viewthread.php?tid=552224&highlight=rrdtool
http://bbs.chinaunix.net/viewthread.php?tid=552220&highlight=rrdtool
作者 :ailms <ailms{@}263{dot}net>
版本 :v1
最后修改 :2006/11/17 17:35
**********************************************************************************************************************


一)前言

可能你已经颇不亟待的想知道如何往 RRD  文件插入数据、如何绘图了吧?hoho ,先别急,在你做这些事情之前,最好先思考以下几个问题 :

A
)如果给你一个 RRD  文件,你能知道它的第一次/ 最后一次 update  的时间是在什么时候吗?

B
)如果你很久之前建立了一个 RRD  文件,现在因为工作原因需要对该 RRD  文件进行一些修改。不过遗憾的是,

   
你已经不记得得当初设置的具体选项和参数了,    这时候该怎么办呢?
   
这两个问题就对应今天要讲的两个操作 :first/last info 

first 
就是用于查看该 RRD  文件中某个 RRA  的第一个数据是在什么时候插入的(或者说第一次更新);

last 
就是查看该 RRD  文件的最近一次更新;

info
就是查看 rrd  文件的结构信息。

下面就以实际例子来看一下该怎么用这三个命令 :


二)如何查询一个 RRD  文件的结构信息

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool info eth0.rrd  (由于输出信息较多,截取了一部分)
filename = "eth0.rrd"
rrd_version = "0003"
step = 300 # RRDtool 
希望每5 分钟收到一个数据
last_update = 1163862985 # 
这是最近一次更新的 timestamp  。可以用 date  转换为具体的时间
ds[eth0_in].type = "COUNTER" # 
有一个名为 eth0_in  DSDST COUNTER
ds[eth0_in].minimal_heartbeat = 600 # hearbeat 
时间是600 
ds[eth0_in].min = 0.0000000000e+00 # eth0_in 
的最小值是 0 bytes
ds[eth0_in].max = 1.2500000000e+07 # eth0_in 
的最大值是 1250000000 bytes
ds[eth0_in].last_ds = "UNKN" 
ds[eth0_in].value = 0.0000000000e+00
ds[eth0_in].unknown_sec = 85
ds[eth0_out].type = "COUNTER"
ds[eth0_out].minimal_heartbeat = 600
ds[eth0_out].min = 0.0000000000e+00
ds[eth0_out].max = 1.2500000000e+07
ds[eth0_out].last_ds = "UNKN"
ds[eth0_out].value = 0.0000000000e+00
ds[eth0_out].unknown_sec = 85
rra[0].cf = "AVERAGE" # 
第一个 RRA  的编号是0 ,不是1
rra[0].rows = 600 # 
共保存 600  个记录
rra[0].pdp_per_row = 1 # 
每个 CDP  由一个 PDP  统计得出
rra[0].xff = 5.0000000000e-01 # 
只要当前interval  PDP  unknown  ,则该 CDP  的值也是unknown
rra[0].cdp_prep[0].value = NaN
rra[0].cdp_prep[0].unknown_datapoints = 0
rra[0].cdp_prep[1].value = NaN
rra[0].cdp_prep[1].unknown_datapoints = 0
rra[1].cf = "AVERAGE" # 
第二个 RRA  的编号是 1 。同样也是 AVERAGE  型。
rra[1].rows = 600 # 
也是保存 600  个记录
rra[1].pdp_per_row = 4 # 
每个 CDP 4 PDP  的求平均值得出
rra[1].xff = 5.0000000000e-01 # 
每个 CDP  最多允许2 PDP  unknown  ,超过则该 CDP unknown
rra[1].cdp_prep[0].value = NaN
rra[1].cdp_prep[0].unknown_datapoints = 3
rra[1].cdp_prep[1].value = NaN
rra[1].cdp_prep[1].unknown_datapoints = 3
[root@dns1 bob]#


由于信息太长,这里截取了后面2 RRA  的信息。


三)第一次更新/ 最近一次更新

如果想知道最近一次更新发生在什么时候,除了可以用上面的 info  操作,还可以用 last  操作

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool last eth0.rrd
1163862985
[root@dns1 bob]#


如果转换成具体的时间就是 :

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool last eth0.rrd |xargs -i date -d '1970-01-01 {} sec utc'
 11 18 23:16:25 CST 2006
[root@dns1 bob]#



[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool first eth0.rrd
1163683200
[root@dns1 bob]#


如果换成具体的时间就是 :

[Copy to clipboard]

CODE:

[root@dns1 bob]# [root@dns1 bob]# rrdtool first eth0.rrd |xargs -i date -d '1970-01-01 {} sec utc' 
 11 16 21:20:00 CST 2006
[root@dns1 bob]#


这三个命令的语法都非常简单,但并不可以因此小看它们的功能,尤其是 info  操作。日后如果需要对 RRD  文件进行调整,是经常需要用到的。

更新 RRD  文件

**********************************************************************************************************************
注 :该教程参考了如下内容 :
A
)官方文档 :http://oss.oetiker.ch/rrdtool/doc/index.en.html
B
abel  兄的大作 :http://bbs.chinaunix.net/viewthread.php?tid=552224&highlight=rrdtool
http://bbs.chinaunix.net/viewthread.php?tid=552220&highlight=rrdtool
作者 :ailms <ailms{@}263{dot}net>
版本 :v1
最后修改 :2006/11/17 17:35
**********************************************************************************************************************


一)前言

写了N 多东东,总算到了 update  部分了。这里有必要比较一下 RRDtool  MRTG  update  方面的差别。

A
MRTG  可以通过 SNMP  协议直接访问 SNMP  对象,你只需要在 cfg  文件中的 Target  指定 OID MRTG  就可以自动替你取回数据。

   
例如Target[as1_eth0]: 2:n7css@172.17.64.11:::::1  ,表示使用 SNMP v1  协议访问 172.17.64.11  主机上 index  2  的那个接口,

   
默认是取 ifInOctets  ifOutOctets  这两个对象的值。RRDtool  则没有这个功能,只能你自己写脚本取数据。
   
B
MRTG  只支持 COUNTER  GAUGE  类型的 Target RRDtool  则还可以使用 DERIVEABSOLUTECOMPUTE
  
C
)由于上面的原因,MRTG  无法识别小数,负数。例如你给 MRTG  一个 -1  的值,它会解释为 1  ;这点可以通过 LOG  看出来。
  
   
小数也不行。例如 .72 bc  的输出)会被识别为 72  ,而不是 0.72
   
D
MRTG  每次 update  每次运行只更新一次,或者说只插入一行记录。但 RRDtool  可以在一个 updat 操作中插入多个记录。

E
MRTG  一次要求2 个值,RRDtool  则没有该方面的限制。

F
)最大的一个区别是, MRTG  在收到一个值后会自动得出 timestamp  ,并记录在 log  的第一个字段;而 RRDtool  是需要你给出一个 timestamp 
  
   
表示该数据是什么时间采集的。

二)update  操作的语法格式

[Copy to clipboard]

CODE:

rrdtool {update | updatev} filename 
      [--template|-t ds-name[:ds-name]...]
      N|timestamp:value[:value...] 
      at-timestamp@value[:value...]
      [timestamp:value[:value...] ...]


表示 now  的意思,会被 RRDtool  替换为当前的 timestamp  ,也就是 date +%s  的结果。Timestamp  部分比较灵活,可以是数字形式,也可以是

AT-
风格的时间(参考 at  命令的 manual ),有点类似于自然语言的风格。


三)手工方式 update  数据库

我们先学习一下如何手工 update  数据库。Update  命令分成两部分 :

A
)时间戳 (timestamp ):表示该数据是在那个时间点采集的。Timestamp  的格式可以非常灵活 :

数字形式 : 例如1164419418  ,表示 “ 11 25 09:50:18 CST 2006” 。通常用于手工插入的方式。

快捷方式 : 。字母 表示当前时间(Now )。如果是通过 crontab  的方式来运行 update  操作,这是最实用的方式。

AT-
风格 : 所谓的 AT  风格的时间,可以参考 at  命令的 manual 。例如 nowyesterdaynow-1hournow+5min  都是 AT 风格的时间。

                        
要注意的是,如果使用 AT 风格的时间,则时间和第一个value 之间使用 @  分隔,而不是 “:”

B
)数值部分 :一个 RRD  文件可以有多个 DS  ,所以一次 update  可以给出多个 value  。多个 value  之间用 “:”  分隔。不过是不是所有的 DS  都必须

    
给出值呢?不一定。有时候你只想给出一部分 DS  的值,甚至有时候某些类型的 DS  是不允许赋值的,例如 COMPUTE  型的 DS  就是这样一个例子。
   

四)实际操作

实例一 :一个错误的例子

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool update eth0.rrd 1163862980:1:2 
ERROR: illegal attempt to update using time 0 when last update time is 1163862985 (minimum one second step)
[root@dns1 bob]#


咦?为什么出错了呢?是语法错误吗?不是的,RRDtool  提示最近一次更新是在1163862985  这个时候。也就是说,update  给出的时间戳必须大于该值。

不能等于或者小于该时刻。因为数据一旦插入到 RRA  中,就不允许再次修改。所以 update  会检查给出的时间戳是否大于最后一次更新的时间戳,如果不是

则报错,不予执行。那如何才能知道最近一次更新的时间戳呢?还记得前一篇 如何获取RRD 文件的信息 中介绍的 last  info  命令吗?对了!就是它们。

执行一下看看是什么结果 ?

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool last eth0.rrd
1163862985 
[root@dns1 bob]#


last 
操作显示的时间戳和上面的报错信息给出的值一样。这个时间是

[Copy to clipboard]

CODE:

[root@dns1 bob]# date -d '1970-01-01 1163862985 sec utc'
 11 18 23:16:25 CST 2006
[root@dns1 bob]#


总之如果要 update  数据库,则 update  操作给出的时间戳必须晚于最后一次 update  的时间。


实例二 :还是一个错误的例子

我们挑 23:16 的下一个5 分钟23:20 作为时间戳吧。

[Copy to clipboard]

CODE:

[root@dns1 bob]# date -d '2006-11-18 23:20' +%s
1163863200
[root@dns1 bob]#


所以 update  命令为 :

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool update eth0.rrd 1163863200:1
ERROR: expected 2 data source readings (got 1) from 1163863200:1:...
[root@dns1 bob]#


还是不行?!!

仔细看错误信息,原来是我们给少了一个值。还记得 info  命令吗?这会儿它派上用场了。

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool info eth0.rrd
filename = "eth0.rrd"
…..(
省略)
last_update = 1163862985
ds[eth0_in].type = "COUNTER"
ds[eth0_out].type = "COUNTER"


原来是2 DS  ,怪不得 RRDtool  会报错了

实例三 :这次应该成功了吧?

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool update eth0.rrd 1163863200:1:2
[root@dns1 bob]#


这会倒是没有错误信息,那究竟数据是否别插入到 RRA  中了呢?

对于该问题,有两个方法,一个是通过 fetch  操作,从 RRA  中提取数据;但这个我们下一篇再讲。

还有一种方法就是用 updatev  操作来代替 update updatev  v  表示 verbose  的意思,现在就来看 updatev  的作用 :


实例四 :updatev  的好处 

我们执行多个 update  操作

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool last eth0.rrd
1163864400
[root@dns1 bob]#
[root@dns1 bob]# rrdtool update eth0.rrd 1163864700:3000:4000
[root@dns1 bob]# rrdtool updatev eth0.rrd 1163865000:3300:4600
return_value = 0
[1163865000]RRA[AVERAGE][1]DS[eth0_in] = 1.0000000000e+00
[1163865000]RRA[AVERAGE][1]DS[eth0_out] = 2.0000000000e+00


可以看到 return value  0 ,这个 return value  你可以理解为 shell  编程中的 exit status updatev 0  表示成功,-1  表示失败。

不过我们插入的值明明是 3300  4600  ,为什么出来的结果是 1 呢?

这是因为 eth0_in  eth0_out  都是 COUNTER  型的 DS ,所以 RRDtool  在收到 3300  4600  后,会作一个运算,就是

3300-3000/ step 300= 1 ,(4600-4000/step300=2  ,这就是 1 2  这两个值的来源了。还记得前面提到的 PDP  吗?

这两个值 (2 )就是 PDP  了,而不是 3300  4600    。这点要搞清楚。


实例五 :另外一个 updatev  的例子

[Copy to clipboard]

CODE:

[root@dns1 bob]#
[root@dns1 bob]# rrdtool updatev eth0.rrd 1163865300:3300:4600
return_value = 0
[1163865300]RRA[AVERAGE][1]DS[eth0_in] = 0.0000000000e+00
[1163865300]RRA[AVERAGE][1]DS[eth0_out] = 0.0000000000e+00
[root@dns1 bob]#


1163865300  这个时刻我们给出的值和上次一样,所以 eth0_in  eth0_out  PDP  都为 0 

搞清楚了 PDP  的概念,现在我们来看什么是 CDP  ,以及 CDP  是如何计算的


实例六 :通过 updatev  掌握 CF  的概念

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool updatev eth0.rrd 1163865600:4000:5000
return_value = 0
[1163865600]RRA[AVERAGE][1]DS[eth0_in] = 2.3333333333e+00
[1163865600]RRA[AVERAGE][1]DS[eth0_out] = 1.3333333333e+00
[1163865600]RRA[AVERAGE][4]DS[eth0_in] = 1.6666666667e+00
[1163865600]RRA[AVERAGE][4]DS[eth0_out] = 1.6666666667e+00
[1163865600]RRA[AVERAGE][24]DS[eth0_in] = NaN
[1163865600]RRA[AVERAGE][24]DS[eth0_out] = NaN
[root@dns1 bob]#


这次的输出和上次又不一样了。这次 update  操作影响到几个 RRA  ,看到 []  中的 1424  了吗?它们就是代表不同的 RRA  中每个 CDP  所包含的 PDP  数量。

就是 1 CDP  包含 PDP 就是 一个 CDP  包含4 PDP20 分钟)、24  就是 一个 CDP  包含24 PDP2 小时)。

不过为什么没有 288  呢?eth0.rrd  的第4 RRA  不是规定每288 PDP  合并为一个 CDP  吗?

因为这个时候还轮不到它出场。1163865600 / 7200 = 161648 ,  也就是说刚好1163865600  是在 7200  的某个周期上(161648 )。

1163865600 / 86400 ≈ 13470.66  ,说明1163865600  还不到 86400  的周期。

必须等到13471* 86400=1163894400  才会出现 [288]  CDP ,那这个时间戳代表的时间是什么时候呢?看下面的 date  命令就知道了 :

[Copy to clipboard]

CODE:

[root@dns1 bob]# date -d '1970-01-01 1163894400 sec utc'
 11 19 08:00:00 CST 2006
[root@dns1 bob]#
[root@dns1 root]# date -d '1970-01-01 1163865600 sec utc' 
 11 19 00:00:00 CST 2006
[root@dns1 root]#


这样不就是刚好相差1 天的时间了吗?你可能会觉得很奇怪,为什么不是00:00  而是 08:00 呢?

还记得create  操作的语法吗?其中有一个 –-start  参数吗?不记得了?没关系,那就得用 first  操作来重新找出来,

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool first eth0.rrd --rraindex 3
1100822400
[root@dns1 bob]#
[root@dns1 bob]# date -d '1970-01-01 1100822400 sec utc'
 11 19 08:00:00 CST 2004
[root@dns1 bob]#


看到了吗?是 2004  年的 11 月19 日早上8 点正,距离 2006-11-19  刚好是2 年,也就是 730 , 因为 eth0.rrd  的第4RRA 

只保存730 个记录。每个记录时间上相差1 天。也就是第一个记录是 2004/11/19 8:00 , 第二个记录是 2004/11/20 8:00 

第三个记录代表 2004/11/21 8:00  ,依次类推。所以离1163865600  最近的下一个记录是发生在 2006/11/19 8:00 

所以严格意义上来说,RRDtool  中的一天并不一定是从 0:00  开始的,但可以保证的就是两个记录之间肯定相差86400 秒(1 天)。


四)自动更新数据库

其实这些都只不过是手工 update  时需要注意的一些地方,如果是自动更新数据库,时间戳方面就交给 RRDtool  去处理吧,我们不用操心了。

前面我们已经写好了一个脚本,现在就用它来更新

[Copy to clipboard]

CODE:

[root@dns1 bob]# cat get_eth0_traffic.sh 
#!/bin/bash

首先取得 eth0  接口的 ifIndex 

index=$(snmpwalk -IR localhost RFC1213-MIB::ifDescr |grep eth0|cut -d '=' -f 1|cut -d '.' -f 2)

再通过 snmp  协议取得 ififInOctets  ifOutOctets  的值

由于在 /etc/snmp.conf  中配置了 defVersion  defCommunity  ,所以 snmpget  命令不用指定这两个参数

eth0_in=$(snmpget -IR -Os localhost ifInOctets.${index}|cut -d ':' -f 2|tr -d '[:blank:]')

eth0_out=$(snmpget -IR -Os localhost ifOutOctets.${index}|cut -d ':' -f 2 |tr -d '[:blank:]')

echo ${eth0_in}

echo ${eth0_out}

需要我要用这些数据来更新 eth0.rrd  ,注意 update  时的 timestamp  我们用的是 N 

/usr/local/rrdtool-1.2.14/bin/rrdtool updatev /home/bob/eth0.rrd N:${eth0_in}:${eth0_out}

[root@dns1 bob]#


五)接下来是什么呢?

有了数据,下面该学什么了呢?是绘图吗?

不是!^_^!!  (估计有人快疯了吧)

在绘图之前,你有没有想过 RRDtool  在绘图时如何取数据的呢?

例如我想画2 小时内的数据,那么我们有4 RRA  ,其 resolution  分别是 3001200720086400 

(还记得什么是 resolution  吗?就是每个 RRA  中两个 CDP  相隔的时间)。是从第一个 RRA  取出 7200/300=24  个记录,

还是从第二个 RRA  取出 7200/1200=6  个记录呢?或者是从第三个 RRA  中取出1 个记录就可以呢?

这些问题我们就留待下一篇再学习吧。这里给大家留几个问题 :


QUOTE:

A ) 如果 eth0.rrd 5 分钟内收到不止1 个更新,结果会怎样?提示:用 updatev  就可以看出来了

B
) 如果过了 eth0.rrd 5 分钟内没有收到脚本返回的值,是否立即就用 UNKNOWN  作为 PDP  的值?

C
) 参考上面的例子,搞清楚 heartbeat  的含义

D
) 在搞清楚 heartbeat  后,再想一下 heartbeat  step  之间的关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值