ailms
RRDtool简体中文教程 v1.01
RRDtool 简介
[color=blue]
****************************************************************************************
注 :该教程参考了如下内容 :
A)官方文档 :[url]http://oss.oetiker.ch/rrdtool/doc/index.en.html[/url]
B)abel 兄的大作 :[url]http://bbs.chinaunix.net/viewthread.php?tid=552224&highlight=rrdtool[/url]
[url]http://bbs.chinaunix.net/viewthread.php?tid=552220&highlight=rrdtool[/url]
作者 :ailms <ailms{@}263{dot}net>
版本 :v1
最后修改 :2006/12/6 22:20
*2006/12/06 :修正了第4篇中 create 命令中 RRA 行数的错误
****************************************************************************************
[/color]
在介绍 RRDtool 之前,让我们先回顾一下它的前身:MRTG。相信只要做网管工作的朋友,对 MRTG 这个软件一定不会陌生,
至少也可能听过。MRTG 可以通过 SNMP 协议直接访问 SNMP Object ,例如 ifInOctect 和 ifOutOctect ;也可以通过外部
script 的方式,来监测cpu、内存、磁盘利用率、数据库的表空间利用率等信息。只要把 MRTG 放入 crontab 中让其自动运行,
MRTG 就可以自动为你绘制出每天、每周、每月、每年的统计图表。 MRTG 甚至还为你提供了自动生成配置文件的 cfgmaker 和
自动生成 HTML 页面的 indexmaker 这两个工具,让你省去逐个编写 cfg 文件的痛苦。到目前为止,还有很多人在使用它。它现在
有 Unix、Windows 各种平台,windows 平台上甚至出现了 PRTG 这样和 MRTG 很象的东东,轻点鼠标就可以漂亮的完成工作。
既然如此,我们为什么还要介绍 RRDtool 呢?先让我们看几个问题,几个在 MRTG 使用中常见的问题 :
[size=4][b] 一)MRTG 不能作什么?[/b][/size]
A)[color=blue]MRTG 一张图表只能显示2个对象,一个输入,一个输出。[/color]如果你想同时显示多个对象呢?例如笔者的单位有12台服务器。如果想
把它们的负载情况都显示在一个图表上,MRTG 至少需要6张图。
B)[color=blue]MRTG无法回放数据。[/color]MRTG 的图是自动生成的,所采用的数据也是由 MRTG 自己提取的,例如5分钟平均的记录有288条, MRTG每20分钟合并一次,
每次合并4个记录。在50个小时后,288条记录将全部变成20分钟平均的数据。如果你想回放这些数据怎么办呢?对不起,只能去
看第2个图了(每周)。
C)[color=blue]MRTG 只有 COUNTER 和 GAUGE 这两种计算类新。[/color]如果我要监测两个数值型的对象之间的大小,它们之间的差值可以是正数,也可以
是负数。MRTG 能实现吗?笔者在多次试验中发现,MRTG 对于负数的和 ‘.15’ 这样格式的小数(通常都是bc的输出)的识别会出错。
例如把 ‘.72’ 识别为 72,把 -1 识别为 1。
D)[color=blue]MRTG 无法实现有条件的绘图。[/color]有时候我们只想看某个服务器在一年之中的宕机时间,正常时间我们不关心;或者我们想看当前值和去年同期相比究竟如何? 这些都是
MRTG无法做到的
[size=4][b]二) MRTG 的优点[/b][/size]
那 MRTG 和 RRDtool 相比就没有优点了吗?也不是。[b]简单、方便[/b]就是它的最大优点。
(MRTG 中还有一个好东西就是自动告警功能,相比之下,RRDtool 在这方面的配置比较复杂,
还不如直接作到 shell script中)
前面提到 MRTG 能够通过 cfgmaker 和 indexmaker 快速建立配置文件和HTML页面。而 RRDtool 在这两方面都需要自己动手。
数据的采集→插入数据→提取数据→绘图→建立 HTML ,这些步骤都是需要你自己动手的。RRDtool 给了使用它的人最大程度的自由。但这种
自由对于新手或者没有耐心的人来说可能是一种考验。相比之下,MRTG 就容易上手多了。
[size=4][b] 三) RRDtool 的定义[/b][/size]
RRDtool 代表 “Round Robin Database tool” ,作者同时也是 MRTG 软件的发明人。官方站点位于[url]http://oss.oetiker.ch/rrdtool/[/url] 。
所谓的“Round Robin” 其实是一种存储数据的方式,使用固定大小的空间来存储数据,并有一个指针指向最新的数据的位置。我们可以把用于存储
数据的数据库的空间看成一个圆,上面有很多刻度。这些刻度所在的位置就代表用于存储数据的地方。所谓指针,可以认为是从圆心指向这些刻度的
一条直线。指针会随着数据的读写操作自动移动。要注意的是,这个圆没有起点和终点,所以指针可以一直移动,而不用担心到达终点后就无法前进
的问题。在一段时间后,当所有的空间都存满了数据,就又从头开始存放。这样整个存储空间的大小就是一个固定的数值。所以RRDtool 就是使用类似
的方式来存放数据的工具,RRDtool 所使用的数据库文件的后缀名是 ‘.rrd’。
[size=4][b] 四)RRDtool 的特殊之处[/b][/size]
A) 首先 RRDtool 存储数据,扮演了一个后台工具的角色。但同时 RRDtool 又允许创建图表,这使得 RRDtoo 看起来又像是前端工具。其他的数据库
只能存储数据,不能创建图表。
B) RDtool 的每个 rrd 文件的大小是固定的,而普通的数据库文件的大小是随着时间而增加的
C) 其他数据库只是被动的接受数据, RRDtool 可以对收到的数据进行计算,例如前后两个数据的变化程度(rate of change),并存储该结果。
D) RRDtool 要求定时获取数据,其他数据库则没有该要求。如果在一个时间间隔内(heartbeat)没有收到值,则会用 UNKN 代替,其他数据库则不会这样做
[size=4][b] 五)总结RRDtool 和 MRTG 的不同之处[/b][/size]
A) MRTG 是采用配置文件的方式来监控的;
RRDtool 则没有配置文件一说。所有操作都是通过命令(也可以写成script方式)执行
B) MRTG 有自动采集数据的功能(通过 snmp);
RRDtool 没有,需要手工或者通过 shell/perl 脚本来获取数据
C) MRTG 每次运行都会更新图片和日志;
RRDtool 默认知识接收数据,并不会绘图,除非手工执行 graph 命令
D) MRTG 采用明文的 log 方式存放历史数据;
RRDtool 采用数据库的方式来存放数据;
E) MRTG 无法回放日志数据,因为 MRTG 会对日志进行合并;
RRDtool 采用 RRA 的概念,把不同统计周期的数据单独存放,所以可以做到历史数据的回放功能
F) MRTG 的 log 中每种周期的记录的数量是自动维护的;
RRDtool 的 RRA 中的记录数是可以自定义的。
G) MRTG 中数据的统计时间间隔是固定的,例如 5分钟平均,30分钟平均,2小时平均,1天平均;
RRDtool 可以任意设置(试过1分钟一次)
H) MRTG 一张图只能显示2个对象;
RRDtool 可以显示多个。
I) MRTG 的数据类型只有 COUNTER 和 GAUGE 两种;
RRDtool 有5种,COUNTER、GAUGE、DERIVE、ABSOLUTE、COMPUTE
J) MRTG 的图表只能显示当前值、最大值、平均值;
RRDtool 可以显示当前值(LAST)、初值(FIRST)、最大值(MAX)、最小值(MIN)、平均值(AVG)、总和(TOTAL)等
K) MRTG 绘图方式只有 AREA、LINE 方式;
RRDtool 则有 AREA、LINE(1|2|3)、STACK 方式;
L) MRTG 负责搜集、存储、绘图、建档(HTML);
RRDtool 只负责存储、绘图这两个阶段,所以需要自己建立 HTML 文件
M) MRTG 的运算功能较差;
RRDtool 可以通过 CDEF 对取出来的数据进行算术和逻辑运算;
N)MRTG 只能原原本本的显示数据;
RRDtool 可以对数据进行处理,或者有条件的显示;
看来 RRDtool 的功能是不是比 MRTG 强很多呢?!
[color=red]具体的差异目前就只能想到这些,不知各位还有没有什么补充呢? !!^_^ !![/color]
相信这么讲的话还是比较抽象的,不过不用急,目前只是一个开始而已。
下一节我们开始讲如何安装 RRDtool 。
[[i] 本帖最后由 ailms 于 2007-10-17 18:13 编辑 [/i]]
ailms
建立 RRD 数据库
[color=blue]
**********************************************************************************************************************
注 :该教程参考了如下内容 :
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
**********************************************************************************************************************
[/color]
准备工作都做完了,脚本也写完了,就可以开始建库了。建库实际上就是建立后缀名为 .rrd 的 RRD 文件。
[size=4][b]一)语法格式[/b][/size]
[code]
rrdtool create filename [--start|-b start time] [--step|-s step]
[DS:ds-name:DST:dst arguments]
[RRA:CF:cf arguments]
[/code]
其中 filename 、DS 部分和 RRA 部分是必须的。其他两个参数可免。
[size=4][b]二)参数解释[/b][/size]
A)[b]<filename> :[/b]默认是以 .rrd 结尾,但也以随你设定。
B) [b]--step :[/b]就是 RRDtool “期望” 每隔多长时间就收到一个值。和 MRTG 的 interval 同样含义。默认是5分钟。我们的脚本也应该是
每5分钟运行一次。
C) [b]--start :[/b]给出 RRDtool 的第一个记录的起始时间。RRDtool 不会接受任何采样时间小于或者等于指定时间的数据。也就是说 –-start
指定了数据库最早的那个记录是从什么时候开始的。如果 update 操作中给出的时间在 –-start 之前,则 RRDtool拒绝接受。--satrt 选项也是
可选的。按照 我们在前一篇中的设定,则默认是当前时间减去 600*300秒,也就是50个小时前。 如果你想指定--start 为1天前,可以用
[code]
--start $(date -d '1 days aog' +%s)
[/code]
注意,--start 选项的值必须是 timestamp 的格式。
D) [b]DS :[/b]DS 用于定义 Data Soure 。也就是用于存放脚本的结果的变量名(DSN)。
就是我们前面提到的 eth0_in ,eth0_out, lo_in , lo_out 。DSN 从 1-19 个字符,必须是 0-9,a-z,A-Z 。
E) [b]DST :[/b]DST 就是 Data Source Type 的意思。有 COUNTER、GUAGE、DERIVE、ABSOLUTE、COMPUTE 5种。
由于网卡流量属于计数器型,所以这里应该为 COUNTER 。
F) [b]RRA :[/b]RRA 用于指定数据如何存放。我们可以把一个RRA 看成一个表,各保存不同 interval 的统计结果
G)[b]PDP :[/b]Primary Data Point 。正常情况下每个 interval RRDtool 都会收到一个值;RRDtool 在收到脚本给来的值后 会计算出另外
一个值(例如平均值),这个 值就是 PDP ;这个值代表的一般是“xxx/秒”的含义。注意,该值不一定等于RRDtool 收到的那个值。除非是
GAUGE ,可以看下面的例子就知道了
H) [b]CF :[/b]CF 就是 Consolidation Function 的缩写。也就是合并(统计)功能。有 AVERAGE、MAX、MIN、LAST 四种
分别表示对多个PDP 进行取平均、取最大值、取最小值、取当前值四种类型。具体作用等到 update 操作时 再说。
I) CDP :Consolidation Data Point 。RRDtool 使用多个 PDP 合并为(计算出)一个 CDP。也就是执行上面 的CF 操作后的结果。这个值就是存入 RRA
的数据,绘图时使用的也是这些数据。
[size=4][b] 三)再说 DST [/b][/size]
DST 的选择是十分重要的,如果选错了 DST ,即使你的脚本取的数据是对的,放入 RRDtool 后也是错误的,更不用提画出来的图是否有意义了。
如何选择 DST 看下面的描述 :
A)COUNTER :必须是递增的,除非是计数器溢出(overflows)。在这种情况下,RRDtool 会自动修改收到的值。例如网络接口流量、收到的
packets 数量都属于这一类型。
B)DERIVE:和 COUNTER 类似。但可以是递增,也可以递减,或者一会增加一会儿减少。
C)ABSOLUTE :ABSOLUTE 比较特殊,它每次都假定前一个interval的值是0,再计算平均值。
D)GAUGE :GAGUE 和上面三种不同,它没有“平均”的概念,RRDtool 收到值之后字节存入 RRA 中
E)COMPUTE :COMPUTE 比较特殊,它并不接受输入,它的定义是一个表达式,能够引用其他DS并自动计算出某个值。例如
[code]DS:eth0_bytes:COUNTER:600:0:U DS:eth0_bits:COMPUTE:bytes,8,* [/code]
则 eth0_bytes 每得到一个值,eth0_bits 会自动计算出它的值:将 eth0_bytes 的值乘以 8 。不过 COMPUTE 型的 DS 有个限制,只能应用
它所在的 RRD 的 DS ,不能引用其他 RRD 的 DS。 COMPUTE 型 DS 是新版本的 RRDtool 才有的,你也可以用 CDEF 来实现该功能。
F)AVERAGE 类型适合于看“平均”情况,例如一天的平均流量,。所以 AVERAGE 适用于需要知道 ‘xxx/秒’ 这样的需求。但采用 AVERAGE 型时,你并不知道
在每个 CDP 中(假设30分钟平均,6个PDP组成)之中,流量具体是如何变化的,什么时候高,什么时候低。这于需要用到别的统计类型了
G)MAXIMUM 、MINIMUM不适用想知道“xxx/秒”这样的需求,而是适用于想知道某个对象在各个不同时刻的表现的需求,也就是着重点在于各个时间点。
也就是所谓的“趋势”了,还是上面的例子,如果采用 MAXIMUM 或者 MINIMUM 的 CF ,可以看出接口在每个 CDP 的周期内最高是达到多少,最低又是多
少,如果是 AVERAGE 的话,有可能前5个 PDP 都很均匀,但最后一个 PDP 的值发生很大的突变。这时候如果用 AVERAGE 可能是看不出来的,因为突变的部
分被平均分配到整个时间段内了,所以看不出突变这一现象;但如果用 MAXIMUM 就可以清楚的知道在该 CDP 的周期内,曾经有达到某个值的时候。所以用
MAXIMUM 或者 MINIMUM 就可以知道某个对象在某个时间段内最大达到多少,最低低到什么程度。
例如要看某个接口在一天内有没有超过50Mb 流量的时候就要用 MAXIMUM
例如要看磁盘空间的空闲率在一天内有没有低于 20% 的时候就要用 MINIMUM
H)LAST 类型适用于 “累计”的概念,例如从xxx时候到目前共累计xxxx 这样的需求。例如邮件数量,可以用 LAST 来表示 30 分钟内总共收到多少个邮件,同
样 LAST 也没有平均的概念,也就是说不适用于 ‘xxx/秒’ 这样的需求,例如你不能说平均每秒钟多少封邮件这样的说法;同样也不适用于看每个周期内的变化,
例如30分钟内共收到100封邮件,分别是 :第一个5分钟20封,第二个5分钟30封,第三个5分钟没有,第4个5分钟10封,第5个5分钟也没有,第6个5分钟
40封。如果用 MAXIMUM 或者 MINIMUM 就不知道在30分钟内共收到100封邮件,而是得出30和0。所以 LAST 适用于每隔一段时间被观察 对象就会复位的
情况。例如每30分钟就收一次邮件,邮件数量就是 LAST 值,同时现有的新邮件数量就被清零;到下一个30分钟再收一次邮件,又得到一个 30 分钟的 LAST 值。
这样就可以得得出“距离上一次操作后到目前为止共xxx”的需求。(例如距离上一次收取邮件后又共收到100封新邮件)
[size=4][b] 四)DST 实例说明[/b][/size]
这样说可能还是比较模糊,可以看下面的例子,体会一下什么是 DST 和 PDP :
[quote]
Values = 300, 600, 900, 1200 # 假设 RRDtool 收到4个值,分别是300,600,900,1200
Step = 300 seconds # step 为 300
COUNTER = 1,1, 1,1 # (300-0)/300,(600-300)/300,(900-600)/300,(1200-900)/300 ,所以结果为 1,1,1,1
DERIVE = 1,1,1,1 # 同上
ABSOLUTE = 1,2,3,4 # (300-0)/300,(600-0)/300 , (900-0)/300, (1200-0)/300,所以结果为 1,2,3,4
GAUGE = 300,600,900,1200 # 300 , 600 ,900 ,1200 不做运算,直接存入数据库
[/quote]
所以第一行的 values 并不是 PDP ,后面4行才是 PDP
[size=4][b] 五)开始建库[/b][/size]
[code]
[root@dns1 root]# rrdtool create eth0.rrd /
> --start $(date –d ‘1 days ago’ +%s) /
> --step 300 /
> DS:eth0_in:COUNTER:600:0:12500000 / # 600 是 heartbeat;0 是最小值;12500000 表示最大值;
> DS:eth0_out:COUNER:600:0:12500000 / # 如果没有最小值/最大值,可以用 U 代替,例如 U:U
> RRA:AVERAGE:0.5:1:600 / # 1 表示对1个 PDP 取平均。实际上就等于 PDP 的值
> RRA:AVERAGE:0.5:4:600 / # 4 表示每4个 PDP 合成为一个 CDP,也就是20分钟。方法是对4个PDP取平均,
> RRA:AVERAGE:0.5:24:600 / # 同上,但改为24个,也就是24*5=120分钟=2小时。
> RRA:AVERAGE:0.5:288:730 # 同上,但改为288个,也就是 288*5=1440分钟=1天
[root@dns1 root]#
[/code]
[color=red]注:上面第2-4个 RRA的记录数实际上应该是 700,775,790,而不是 600,600,730。
600 samples of 5 minutes (2 days and 2 hours)= 180000 秒 (2.08天)
700 samples of 30 minutes (2 days and 2 hours, plus 12.5 days)= 1260000 秒 (14.58天 ,2周)
775 samples of 2 hours (above + 50 days) = 5580000 秒 (64.58 天,2个月)
797 samples of 1 day (above + 732 days, rounded up to 797) = 68860800 秒(2年)
可以看出每个 RRA 都存储了相应单位2倍时间的数据,例如每天的 RRA 存储2天的数据,每周的 RRA 存储2周的数据,每月的 RRA 存储2个月的数据,每年的 RRA 存储2年的数据
[/color]
检查一下结果
[code]
root@dns1 bob]# ll -h eth0.rrd
-rw-r--r-- 1 root root 41K 11月 19 23:16 eth0.rrd
[root@dns1 bob]#
[/code]
有的人可能会问,上面有两个 DS,那 RRA 中究竟存的是那个 DS 的数据呢?实际上,这些 RRA 是共用的,你只需建立一个 RRA,它就可以用于全部的 DS 。
所以在定义 RRA 时不需要指定是给那个 DS 用的。
[size=4][b]六)什么是 CF [/b][/size]
以第2个RRA 和 4,2,1,3 这4个 PDP 为例
[b]AVERAGE[/b] :则结果为 (4+2+1+3)/4=2.5
[b]MAX[/b] :结果为4个数中的最大值 4
[b]MIN[/b] :结果为4个数中的最小值1
[b]LAST[/b] :结果为4个数中的最后一个 3
同理,第三个RRA和第4个RRA则是每24个 PDP、每288个 PDP 合成为1个 CDP
[size=4][b] 七)解释度(Resolution)[/b][/size]
这里要提到一个 Resolution 的概念,在官方文档中多处提到 resolution 一词。Resolution 究竟是什么?Resolutino 有什么用?
举个例子,如果我们要绘制1小时的数据,也就是60分钟,那么我们可以从第一个RRA 中取出12个 CDP 来绘图;也可以从第2个 RRA
中取出2个 CDP 来绘图。到底 RRDtool 会使用那个呢?
让我们看一下 RRA 的定义 :RRA:AVERAGE:0.5:4:600 。
Resolution 就等于 4 * step = 4 * 300 = 1200 ,也就是说 ,resolution 是每个CDP 所代表的时间范围,或者说 RRA 中每个 CDP(记录)
之间的时间间隔。所以第一个 RRA 的 resolution 是 1* step=300,第2是 1200,第三个是 24*300=7200,第4个 RRA 是 86400 。
默认情况下,RRDtool 会自动挑选合适的 resolution 的那个 RRA 的数据来绘图。我们大可不必关心它。但如果自己想取特定 RRA 的数据,就需要用到它了。
关于 Resolution 我们还会在 fetch 和 graph 操作中提到它。
[size=4][b]八)xff 字段[/b][/size]
细心的朋友可能会发现,在 RRA 的定义中有一个数值,固定是 0.5 ,这个到底是什么东东呢?
这个称为 xff 字段,是 [b]xfile factor [/b] 的缩写。让我们来看它的定义 :
[quote]
The xfiles factor defines what part of a consolidation interval may be made up from *UNKNOWN* data while
the consolidated value is still regarded as known. It is given as the ratio of allowed *UNKNOWN* PDPs to
the number of PDPs in the interval. Thus, it ranges from 0 to 1 (exclusive)
[/quote]
这个看起来有点头晕,我们举个简单的例子 :例如
[code]RRA:AVERAGE:0.5:24:600 [/code]
这个 RRA 中,每24个 PDP (共两小时)就合成为一个 CDP,如果这 24 个 PDP 中有部分值是 UNKNOWN (原因可以很多),例如1个,那么这个 CDP
合成的结果如何呢?是否就为 UNKNOWN 呢?
不是的,这要看 xff 字段而定。Xff 字段实际就是一个比例值。0.5 表示一个 CDP 中的所有 PDP 如果超过一半的值为 UNKNOWN ,则该 CDP 的值就被标为
UNKNOWN。也就是说,如果24个 PDP中有12个或者超过12个 PDP 的值是 UNKNOWN ,则该 CPD 就无法合成,或者合成的结果为 UNKNOWN;
如果是11个 PDP 的值为 UNKNOWN ,则该 CDP 的值等于剩下 13 个 PDP 的平均值。
如果一个 CDP 是有2个 PDP 组成,xff 为 0.5 ,那么只要有一个 PDP 为 UNKNOWN ,则该 PDP 所对应的 CDP 的值就是 UNKNOWN 了
[[i] 本帖最后由 ailms 于 2006-12-6 22:17 编辑 [/i]]
ailms
RRDtool简体中文教程_9:如何使用RPN
如何使用RPN
[color=blue]
**********************************************************************************************************************
注 :该教程参考了如下内容 :
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
**********************************************************************************************************************
[/color]
[size=4][b]一)前言[/b][/size]
RPN 代表逆波兰式(Reverse Polish Notation)。逆波兰式最早于1920年由Jan Lukasiewicz 发明,最神奇的地方是用它来表示数学表达式,
完全不需要括号。而且 RPN 不像普通的数学表达式那样,操作符在操作数的中间,而是在操作数的右边。例如 3+2 用 RPN 表示就是 3,2,+ ;
3+(2X5) 用 RPN 表示就是 3,2,5,x,+ 最后运算的部分(加法部分)的操作符放在最后,乘号放在前面,表示先执行 2 x 5 ,在把结果和3相加。
在 RRDtool 中,RPN 还可以用来表示 if-then-else 关系。这点在绘图中很有用。例如你要看 eth0 接口在一天当中流量 ≥ 10Mb/s 的部分,“隐藏”
其他低于 10Mb/s 的部分,则可以用到这个功能。
[size=4][b]二)操作符[/b][/size]
[b]什么是 RPN[/b]
A)RPN 是 Reverse Polish Notation 的缩写,是用于表示算术运算和逻辑运算的一种语法格式。
B)RRDtool 的 CDEF 语句中就经常使用 RPN 来对 DEF 取出来的数据进行运算。
C)RPN 的特点是操作数和操作符出现的顺序和运算的顺序一致,这样就不需要使用括号了
D)RPN 的格式是 <value1>,<value2>,<operator> ,[<value1>,<value2>,<operator>]… 可以看出是操作数在前,操作符在后的格式
E)RPN 需要提到堆栈的概念(stack)。堆栈是用来存储操作数和操作符的。
F)当堆栈中压入(push)一个操作符时,就从堆栈中取出(pop)所需要的操作数进行计算(根据操作的不同pop出不同数量的操作数)。
结果再返回(push)堆栈,最终整个 RPN 应该只返回一个值,或者说堆栈中只有一个元素
G)在 CDEF 中书写 RPN 操作符,要一律以大写的格式出现
H) RPN 中,如果某个部分的运算结果非 0,则被认为是 true ,只有 0 才被认为是 false
[size=4][b]三)RPN 操作符的分类[/b][/size]
A)布尔操作符 :GT、GE、LT、LE、EQ、NE、
B)特殊值比较符 :UN、ISINF、
C)条件操作符 :IF
D)比较操作符 :MIN、MAX、LIMIT
E)算术操作符 :+ 、-、*、/、%、SIN, COS, LOG, EXP, SQRT、FLOOR, CEIL、ATAN、ATAN2、DEG2RAD, RAD2DEG
F)数据集操作符 :所谓数据集(sets),就是指多个数据。SORT、REV、AVG、TREND
G)特殊值 :UNKN、INF、NEINF、PREV、COUNT
H)时间操作符 :NOW、TIME、LTIME
I)堆栈操作符 :POP、DUP、EXC
[b]四)RPN 操作的结果[/b]
A)布尔操作符 :从堆栈中 pop 出两个元素,并根据比较结果返回 0 (false) 或者 1 。任何同 UNKNOWN 或者 INF 、NEINF 比较的都为 0
B)特殊值比较符 :从堆栈中 pop 出1个元素,并同 UNKNOWN 或者 INF、NEINF 比较。结果为 0 或者 1
C)条件操作符 :从堆栈中pop出3个元素,如果最后pop出的那个元素不为0(条件部分为 true),则第2次 pop 出的那个元素被重新入栈(then部分);
否则第一次pop出的元素重新入栈(else部分)。结果为 then 部分或者 else 部分返回的值,不一定为0或者1
D)比较操作符 :
对于 MIN/MAX 操作符来说,从堆栈中 pop 出两个操作符,并把较大/小的那个重新入栈。如果其中有一个 unknown ,则结果为 unknonw
对于 LIMIT 操作符来说,先从堆栈中 pop 出2个操作数,作为边界的定义;再 pop 出1个操作数,比较该操作数是否落在前面定义的范围内。
如果是则把最后 pop 出的那个元素重新入栈;否则把 UNKN 值入栈;注意,是 UNKN ,不是 0
E)算术操作符 :根据操作符 pop 出所需数量的操作数,并把算术运算的结果重新入栈
F)数据集操作符 :
对于 SORT、REV 来说,先从堆栈中 POP 出一个元素,该元素的值就是下面要 pop 出的元素的数量。然后对堆栈从上到下的若干个元素
由第一次 pop 的出的那个元素的值决定)进行排序/反向排序。结果再重新入栈。
注意 :由于堆栈的特点是后进先出,所以要操作的元素是从SORT操作符往左方向计数。例如v1,v2,v3,v4,3,SORT是对 v2~v4 排序,
不是对 v1~v3 排序。 这点在书写 RPN 时要特别注意。
注意 :SORT 操作是最小值在堆栈的最顶部;REV 则相反,最小值是在堆栈的最顶部。
对于 AVG 操作来说,同样是先 pop 出1个元素,并按照指定的数量对后续的若干个操作数进行操作,但结果只有一个数值,并入栈。
G)特殊值 :
UNKN 表示压入一个 UNKN 值;INF、NEINF 分别表示把 INF、NEINF 值压入堆栈
H)时间操作符 :
TIME 返回当前所提取的记录的 timestamp ,注意 TIME 直接返回当前记录的 timestamp ,不用任何参数
NOW 返回当前时间,同样 NOW 不用任何参数
I)堆栈操作符 :
POP :弹出堆栈的最顶部的那个元素
EXC :交换堆栈顶部的第一个和第二个元素的值
[size=4][b]五)如何阅读 RPN[/b][/size]
A)首先按照从左到右的顺序,找出第一个 RPN 操作符,并根据上一节的内容,对相应的操作数进行操作
B)操作结果分成两种 :
如果是一个值,直接替换掉该部分 RPN
如果是多个值(数据集操作,但 AVG 操作只返回一个值),则结果可能为多个数值。则把这若干个数值用 ‘,’ 隔开,替换原来那部分 RPN
C)如此循环,一直到整个 RPN 只返回一个值为止
[size=4][b]六、RPN 实例[/b][/size]
A)布尔型操作符 :2,1,GE 表示 2>=1 ;
B)特殊值比较符 :mydata,UN 表示 mydata == UNKNOWN
C)条件操作符 :mydata,UN,0,mydata,IF 表示如果 mydata 等于 UNKNOWN ,则返回 0;否则还是返回 mydata 本身
D)比较操作符 :mydata,20,MAX 表示返回 mydata,20 这两个数值中较大的一个;alpha,0,100,LIMIT 表示测试 alpha 的值是否小于等于0,大于等于100;
E)算术操作符 :1,2,- 表示 1-2=-1
F)数据集操作符 :
v1,v2,v3,v4,v5,4,SORT 表示对 v1~v4 进行正向排序,结果堆栈中还是有5个元素;
v1,v2,v3,v4,3,AVG,+,2,/ 表示对 v4,v3,v2 进行求平均值,并把结果入栈。假设v2~v4的结果为 k ,则为 v1,k,+,2,/ 也就是返回 (v1+k)/2
G)特殊值 :mydata,0,GT,UNKN,mydata,IF 表示如果 mydata 大于 0则返回 UNKNOWN ,否则还是 mydata
H)时间操作符 : TIME,`date –d “2006-10-01 10:00” +%s`,GT,0,1,IF 表示如果当前记录的采集时间是在 2006-10-01 10:00 之后就返回1,否则返回 0
I)堆栈操作符 :POP 就立即弹出第一个元素
[size=4][b]七)如何表示 AND、OR 关系[/b][/size]
A)我们知道 RPN 表达式的值除非0,否则都认为是 true
B)我们可以利用 加法操作和乘法操作来实现 OR 和 AND 的逻辑关系;如果两个 RPN 表达式的值相加不等于0,就一定为 true ;
如果两个 RPN 表达式的值相乘不等于0,就一定为 true
C)AND 关系的例子 :例如要比较某个值(15,9)是否在特定范围内可以用 :
15,10,GT,15,20,LT,* ,结果就是(15>10)*(15 < 20)= 1 * 1 =1 ,所以为 true
9,10,GT,9,20,LT,* ,结果就是 (9 >10)* ( 9 < 20)= 0 * 1 =0 ,所以为 false
D)OR 关系的例子:同上例如要比较某个值(7,15)小于10,或者大于20:
7,10,LT,7,20,GT,+ ,结果为 (7 < 10)+ (7 > 20) = 1+0 = 1,所以为 true
15,10,LT,15,20,GT,+ ,结果为 ( 15 < 10) + ( 15 > 20) = 0 + 0 =0 ,所以为 false
E)不过使用 + 需要注意一个地方 :相加的双方都必须是正数,否则可能出现问题,例如一个正数(-5,true)和另外一个正数(5,true)相加为 0(false)
如果是按照 OR 的关系,应该是 true 的,但结果变成0(false),所以在使用 + 来表示 OR 的关系时,要注意该问题
F)使用 * 则没有该问题了,正数 * 负数 = 负数 (true)。所以如果遇到 OR 关系的时候,可以转换为 AND 关系来计算。
例如要表达 (x < a) OR ( x > b) 的关系,可以改为 (x >a) AND ( x < b ) ,诀窍就是把比较操作符调反方向,把 + 改为 *
[size=4][b]八)实例[/b][/size]
[b]实例1:例如要看 eth0的总流量,可以用如下的定义[/b]
[code]
DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=eth0.rrd:eth0_out:AVERAGE /
CDEF:value3=value1,value2,+ /
AREA:value3#ff0000:”total”
[/code]
[b]实例2 :假设我们要把 eth0 和 lo 的流入流量相加,得出总的流入流量[/b]
[code]
DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=lo.rrd:lo_out:AVERAGE /
CDEF:value3=value2,UN,0,value2,IF /
CDEF:value4=value1,value3,+ /
AREA:value4#00ff00:”total in”
[/code]
由于 lo.rrd 一直没有数据插入,所以一直都是 NaN ,如果直接把 value1 和 value2 相加,由于 value2 是 UNKNOWN,
所以相加的结果也是 UNKNOWN 。图表上将什么都不显示,所以需要对 value2 进行判断,如果 value2 的值 UNKNOWN (value2,UN),
则返回0,否则返回 value2 本身。然后把这个值赋予变量 value3 ,最后把 value1 和 value3 相加,才得出真正入流量
[b]实例3 :只看 eth0 中流量大于 10Mb/s 的部分,其余不看[/b]
[code]
DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=eth0.rrd:eth0-_out:AVERAGE /
CDEF:value3=value1,1000000,GT,value1,UNKN,IF /
CDEF:value4=value2,1000000,GT,value2,UNKN,IF /
AREA:value3#00ff00:”traffic_in /> 10M//s” /
AREA:value4#ff0000:”traffic_out /> 10Mb//s”:STACK
[/code]
[b]实例4 :只绘制特定时间段(在 2006/11/29 10:30 ~ 2006/11/29 12:30)的数据[/b]
[code]
DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=eth0.rrd:eth0_out:AVERAGE /
CDEF:value3=TIME,$(date –d ‘2006-11-29 10:30’ +%s),GT,TIME,$(date –d '2006-11-29 12:30' +%s),LT,*,value1,UNKN,IF /
CDEF:value4=TIME,$(date –d ‘2006-11-29 12:30’ +%s),GT,TIME,$(date –d '2006-11-29 13:30' +%s),LT,*,value2,UNKN,IF /
AREA:value3#00ff00:”traffic_in” /
AREA:value4#ff0000:”traffic_out”:STACK
[/code]
[size=4][b]九、完结[/b][/size]
相信到目前为止,大家对 RRDtool 的认识应该更深了吧。一定要多做实验,这样才能做到熟能生巧,灵活应用。
其实剩下的还有 xport、dump、restore、resize、tune、rrdcgi 几个操作没讲,而且有一些应用经验方面的东西也没有提到,
不过想要全部写出来,可能太耗时间和精力了,这些东西足足写了我2个星期才写完。中间还要不断的做实验以验证正确性,怕误导了大家。
如果需要的话,可以自己下载官方文档学习,或者能有热心的朋友补充就更好了,^_^ 。
[size=4][b]十、 本人的一点学习体会[/b][/size]
本人从开始看 RRDtool 官方文档到开始写这篇教程,差不多用了2个月。 RRDtool 比学习 MRTG 难多了,资料少,RRDtool 的中文资料目前就只有 abel
兄写的那一篇教程,如果没有实际的上机操作,是不可能看懂的,所以 abel 兄也特别交代这点。如果只一心想速成,到头来反而吃亏的是自己。
象sendmail、bind 这些服务器的配置,随便在 google 上都可以搜到一大把所谓的“快速入门”,很多人也都照着做了。但明明别人可以的,为什么轮到自己
却失败呢?相信这是很多人心中曾有的郁闷经历。其实归根到底就是基础的问题,再深入一些就是学习心态的问题。“不积跬步,无以至千里;不积小流,无以成江海”。
配置一个服务器并不是照抄配置就可以的。环境的不同,需求的不同这些因素都要考虑在内。怎么可能做到完全一样呢?同一个语句换个环境可能就不行了。所以我很
少看那些所谓的快速入门,要么看 manual ,要么看书(说到这里,感觉 O’Reilly 的书真是不错!^_^),如果是象 RRDtool这种的,就只好看官方文档了。
学习的同时也要注意选择好的教材。有时候一本好书能带给无穷的好处。这点在我第一次看 O’Reilly 的 《dns & bind 4th》就有感觉,老外的书很注重循序渐进,
通常他们都是从某个实际工作环境的一个小例子说起,逐步引入各个命令、配置语句。然后随着需求的壮大,不断引入新的内容,最后形成一个总体。这样看完后会心中会
有一个整体的框架和概念。不象国内一些书,毫不顾及条理,一上来就讲语法、命令,搞得读者很快都没有兴趣。这样的书可谓害人不浅。
同时也建议大家读英文原版的书。为什么呢?虽然中文的看起来快一些,但学习不是竞走比赛。不是比谁看的快,而是比谁学的牢。英文书的词汇其实都是专业词汇,
只要看多了,自然记住了。实在记不住,可以用金山词霸等工具辅助。俺的英文水平只有二级,但并不妨碍我看书。况且看英文书,有一个“英文→中文”的转换的过程。就
是揣摩作者这句话的含义,或者说这句话应该如何翻译好。有些人觉得这个没有什么,但我觉得这个过程是你弄清作者思想的重要步骤。在你不断的揣摩中,可能会有不同
的理解,直到你认为这是最正确的那一种解释为止。如果是看中文书,可能会由于惰性,比较容易就接受作者的想法,而失去这个主动我思考的过程。
一时有感而发,胡乱写了一通,请各位朋友见谅了。
书山有路勤为径,学海无涯苦做舟!
愿以该座右铭和各位有志于Linux的朋友一起共勉!
2006/12/2 22:23