在我看来,学习某个东西的最好办法就是实践。为什么现在不开始呢?我们会创建一个数据库,放一些数值到它里面,然后提取这些数据。
    我们会从一些简单的例子入手,然后把汽车与路由器比较,或者将公里和比特、字节数比较。他们都是一样的:都是某些时段的某些数值。
    假设我们有一个向互联网发送数据和接收数据的设备。该设备保留一个计数器,该计数器在开启设备时设置为0,并在每传送一个字节就加1。该计数器可能会有一个最大值。如果该值达到最大时,在加一个字节的计数,该计数器就会再次从0开始。这与世界上的许多计数器都是一样的,比如车辆上的里程计数器。
    关于网络的讨论通常用每秒比特数来衡量,因此我们要习惯这种用法。把一个字节看成是8个比特,并且开始用比特而不是字节来思考问题。不过,计数器仍然用字节数为单位来计量!在SNMP世界里,大部分的计数器都是32比特的。这就意味着他们的计数范围是0-4294967。我们在例子里会用到这些数值。该设备在被查询时,会返回计数器的当前值。我们知道从上次查询设备开始到现在的时间,因此我们现在就知道每秒平均传输了多少字节数。这不难计算。首先用文字来描述,然后计算:
    (1) 用当前查询到的计数器值,减去上一次查询的计数器值
    (2)把当前查询时间和上次查询时间作上述同样操作(秒)
    将(1)的结果除以(2)的结果,得到的结果就是每秒的字节数。乘以8就得到每秒的比特数(bps)
 bps = (counter_now - counter_before) / (time_now - time_before) * 8
    不习惯用公里/小时的人,可以将公里除以1.6来得到英里/小时(足够精确)。我会用到下面所写:
M : 米
KM: 公里(1000米)
H: 小时
S: 秒
KM/H:公里/小时
M/S: 米/秒
    你现在正在开车。12:05时你看了一下仪表盘上的里程计数器,它显示这俩车已经行驶了12345公里。12:10分时,你有看了一下里程计数器,它显示12357公里。这表示你在5分钟内行驶了12公里。科技人员会把它转换成米/秒,这样可以更好的进行比较(每5分钟的字节数)和(每秒比特数)。
 我们行驶了12公里,也就是12000米。我们在5分钟内,或者说是300秒内完成。我们的速度是1200米/300秒,或者说是40米/秒。
    我们可以用公里/小时来计算速度:12乘以5分钟就是一个小时,因此我们必须把12公里乘以12得到144公里/小时。也就是90英里/小时,因此不要在家里或我生活的地方尝试这个速度 :)
 记住:这些数值都仅仅是平均值。无法从数字中得到你是否以固定的速度在行驶。
 我希望你理解在计算米/秒或者比特/秒。唯一的差别在于收集数据的方式。即使是K这个单位也是一样的,因为在网络术语中,K同样表示1000。
    我们现在要创建一个数据库,在此数据库中我们能够保存所有这些有趣的数字。启动这个程序的方法可能在各个操作系统上各不相同,但是我假设你可以搞清楚它是否与你的操作系统不同,键入下面的行(为了可读性,我得把他分成几行)并且用来分隔。
rrdtool create test.rrd           
         --start 920804400        
         DS:speed:COUNTER:600:U:U 
         RRA:AVERAGE:0.5:1:24     
         RRA:AVERAGE:0.5:6:10
    我们创建的rrd数据库名为test (test.rrd),它的起始时间是1999年3月7日(该日期转换成920804400秒)。我们的数据库存放一个名为 'speed' 的数据源(DS),它表示一个计数器。该计数器每5分钟(缺省)读取一次。在同一个数据库中,保存有2个环状归档(RRA),一个是每次读取时的平均数据并保留24个样本(24乘以5分钟是2小时)。另一个RRA有6个平均值(6X5=30半小时)并包含10个这样的样本。
RRDtool使用来源于UNIX世界的特殊时间戳。该时间戳是自1979年1月1日UTC时间开始到当前逝去的秒数。该时间戳的值被转换成本地时间,它在不同的时区会不一样。
现在我们得向数据库中填入一些数字。我们希望读到以下数据:
12:05 12345 KM
12:10 12357 KM
12:15 12363 KM
12:20 12363 KM
12:25 12363 KM
12:30 12373 KM
12:35 12383 KM
12:40 12393 KM
12:45 12399 KM
12:50 12405 KM
12:55 12411 KM
13:00 12415 KM
13:05 12420 KM
13:10 12422 KM
13:15 12423 KM
我们用下面的命令把上述数据填入数据库:
rrdtool update test.rrd 920804700:12345 920805000:12357 920805300:12363
rrdtool update test.rrd 920805600:12363 920805900:12363 920806200:12373
rrdtool update test.rrd 920806500:12383 920806800:12393 920807100:12399
rrdtool update test.rrd 920807400:12405 920807700:12411 920808000:12415
rrdtool update test.rrd 920808300:12420 920808600:12422 920808900:12423
这就是说:用下面的数据来更新我们的数据库
time 920804700, value 12345
time 920805000, value 12357
等等....
    正如你说看到的那样,可以在一个命令里向数据库中填入多个值。为了可读性,我得只用三个数据,实际一行里运行的最大数据与操作系统相关。
   我们可以使用 rrdtool fetch 命令从数据库中提取数据。
   rrdtool fetch test.rrd AVERAGE --start 920804400 --end 920809200
   该命令会返回如下输出结果:
           speed
920804700: nan
920805000: 4.0000000000e-02
920805300: 2.0000000000e-02
920805600: 0.0000000000e+00
920805900: 0.0000000000e+00
920806200: 3.3333333333e-02
920806500: 3.3333333333e-02
920806800: 3.3333333333e-02
920807100: 2.0000000000e-02
920807400: 2.0000000000e-02
920807700: 2.0000000000e-02
920808000: 1.3333333333e-02
920808300: 1.6666666667e-02
920808600: 6.6666666667e-03
920808900: 3.3333333333e-03
920809200: nan
   如果不是像上面的输出结果,可能哪里有错误。也许你的操作系统会打印出不同的格式。 NaN 表示 非数字 。 如果你的操作系统输出 U 或 UNKN 或者其他类似东西都是正常的。如果其他地方错误,可能是因为你的过程中的那些步骤出错了。
 试试下面的命令:
rrdtool graph speed.png                               
        --start 920804400 --end 920808000             
        DEF:myspeed=test.rrd:speed:AVERAGE            
        LINE2:myspeed#FF0000
    该命令会创建名为speed.png的图像文件,该图像从12:00开始,到13:00。有一个名为myspeed的变量定义,它使用来自 test.rrd数据库的 speed RRA中的数据。绘制的线条是2像素高,表示myspeed变量。颜色是红色的.
 你会注意到图像的起始不是12:00而是12:05。这是因为在此时间之前的数据不够计算出平均值。这只会在缺少某些样本的情况下发生,不会经常发生。
    查看图像时,你会注意到横轴下标为 12:10、12:20、12:30、12:40、12:59。有时某些下标不适合(可能是12:00和13:00)会被忽略掉。
 纵轴显示我们输入的范围。下面提供的公里数,以及除以300秒的结果,我们得到非常小的数值。为了更加精确,第一个值是12(12567-12456),除以300后得到0.04,RRDtool显示时为 40m 表示 40/1000 。 其中的 m 与米、公里、或者毫米都没有任何关系!RRDtool不知道我们的数据单位,它只处理没有单位的数据。
如果我们用米来衡量我们的距离,就会是这样:(12'357'000-12'345'000)/300 = 12'000/300 = 40.
    因为许多人都对这样的数值范围感觉更好,我们就来修正一下。我们将重新创建数据库,并存储正确的数据。但是有更好的办法:在创建png文件时进行一些计算!
rrdtool graph speed2.png                         
     --start 920804400 --end 920808000             
     --vertical-label m/s                          
     DEF:myspeed=test.rrd:speed:AVERAGE            
     CDEF:realspeed=myspeed,1000,*                
     LINE2:realspeed#FF0000
 注意:不要忘记操作符*后面的。这个反斜杆用来将*从操作系统可能解释的符号转义,而不是直接传递给rrdtool命令。
    在查看PNG文件后,你会注意到 m 不见了。正确的结果就是这样。同样,在图像中加入了一个标注(m/s)。出了上面提到的几点外,PNG看起来应当是一样的。
        计算是在CDEF部分中指定的,使用逆波兰表达式( RPN )表示的。我们要求RRDtool所作的事情是:`取数据源myspeed(公里/秒), 以及数值1000;把他们相乘`得到(米/秒) 。在此不要被RPN表达式困扰了。
    在我们的例子数据库中,我们犯了一个错误,我们需要乘以3600来补偿。使用下面的修正办法:
realspeed=myspeed * 3,600(KM/H)
下面我们来创建这个PNG文件,并加入更多的魔幻功能...
rrdtool graph speed3.png                           
     --start 920804400 --end 920808000             
     --vertical-label km/h                         
     DEF:myspeed=test.rrd:speed:AVERAGE            
     "CDEF:kmh=myspeed,3600,*"                     
     CDEF:fast=kmh,100,GT,kmh,0,IF                 
     CDEF:good=kmh,100,GT,0,kmh,IF                 
     HRULE:100#0000FF:"Maximum allowed"            
     AREA:good#00FF00:"Good speed"                 
     AREA:fast#FF0000:"Too fast"
     这个图像看起来更好。速度用KM/H表示,有一个附加的线条表示最大允许的速度(在我行驶的道路上的最大限速)。我还修改了速度的显示颜色,把它从线条改为区块。
现在计算更加复杂一些。对于在限速内的速度good衡量方法是:
检查公里/小时是否大于100          ( kmh,100 ) GT
如果是,返回0,否则返回公里/小时。  ((( kmh,100 ) GT ), 0, kmh) IF
 对于上述的限速值fast:
检查公里/小时是否大于100          ( kmh,100 ) GT
如果是,返回公里/小时,否则返回0。  ((( kmh,100) GT ), kmh, 0) IF
     现在,你所需要做的只有按照常规的方式度量数值,然后更新数据库。当你想查看数据时,重新创建PNG。
 大多数对RRDtool感兴趣的人会使用一个跟踪网络设备传输数据量的计数器。这样我们下一步就来作这个。我们会从解释如何收集数据开始。
     本例中使用的工具在本文档前面非常简短地提到过,它就是所谓的SNMP。它是与联网设备交谈的方式。下面用到的工具名为 snmpget ,以下是关于它是如何工作的说明:
snmpget device password OID

snmpget -v[version] -c[password] device OID
     对于device, 你要用设备的名称或者IP地址来替换。对于password, 你需要使用SNMP领域中称为 comunity read string 来替换。对于某些设备来说,缺省的 public 可以工作,但是该设置可能会被关闭,调整或者由于安全和机密的原因而被保护起来。请阅读你的设备或程序的文档。
    接下来有一个称为OID的参数,它用来表示对象标识符。
    刚开始学习SNMP时,它看起来有些令人困惑。在你看到MIB管理信息库时,就不会那么困难了。MIB是用来描述数据的倒状树,它只有一个根结点,并且由根结点开始有多个分支。这些分支都以另一个结点终结,他们继续向下分支,如此继续。所有的分支都有一个名称,它们构成了一个我们能够沿着往下的路径。我们所沿着的这些分支都被命名了:iso, org, dod, internet, mgmt 和mib-2.这些名称也可以用数字方式记录,就像 1 3 6 1 2 1。
iso.org.dod.internet.mgmt.mib-2 (1.3.6.1.2.1)
     有些程序会使用前导点 . ,令人感到许多困惑。在一个OID中并没有前导点。为了显示OID缩记法和OID完整记法的区别,(通常约定)在使用OID的完整记法时使用前导点。通常这些程序在返回数据给你时,会省略缺省的部分。这些程序有的有几个缺省前缀,这会让事情显得更加糟糕。
    在此我会给出一个在Fedora Core 3操作系统上可用的例子。如果对你的操作系统不可用,请查看snmp的手册,并作相应的调整让它能够运行。
 snmpget -v2c -c public myrouter system.sysDescr.0
    该设备应当回应其自身的描述,该描述可能是一个空的。只有在你从某个设备获得响应后,你才能够继续。其中可能需要使用不同的口令、或者不同的设备。
snmpget -v2c -c public myrouter interfaces.ifNumber.0
    最好你得到的结果是一个数字。如果这样的话,你就可以继续往下,并试试另一个叫做 snmpwalk 的程序。
snmpwalk -v2c -c public myrouter interfaces.ifTable.ifEntry.ifDescr
    如果该命令返回一系列的接口,这就对了。以下是该命令运行的返回结果的例子:
[user@host /home/alex]$ snmpwalk -v2c -c public cisco 2.2.1.2
  interfaces.ifTable.ifEntry.ifDescr.1 = "BRI0: B-Channel 1"
  interfaces.ifTable.ifEntry.ifDescr.2 = "BRI0: B-Channel 2"
  interfaces.ifTable.ifEntry.ifDescr.3 = "BRI0" Hex: 42 52 49 30
 
interfaces.ifTable.ifEntry.ifDescr.4 = "Ethernet0"
 
interfaces.ifTable.ifEntry.ifDescr.5 = "Loopback0"
    对于cisco设备,我想监视`Ethernet0` 接口,从上面的输出结果能够看到该接口的编号是 4。我试着运行如下命令:
[user@host /home/alex]$ snmpget -v2c -c public cisco 2.2.1.10.4 2.2.1.16.4
 interfaces.ifTable.ifEntry.ifInOctets.4 = 2290729126
 interfaces.ifTable.ifEntry.ifOutOctets.4 = 1256486519
 这样,我就有两个OID需要监视,他们是(这次使用完整记法):
1.3.6.1.2.1.2.2.1.10

1.3.6.1.2.1.2.2.1.16
 这两个OID都有接口编号4。
    别被糊弄了,我可不是试一次就搞定的。我花了一些数据来搞清这些数字都是什么意思。把这些编号转换成描述文字大有帮助... 至少在大家谈论MIB和OID时,你知道他们是什么东西。别忘了接口编号(如果它不是附属接口,就是0),如果用snmpget没有得到响应,试试snmpwalk。
    开始有趣的东东吧。首先,创建一个新的数据库。它包含输入和输出2个计数器的数据。该数据被放入能够进行平均的归档中。他们一次使用1、6、24、或 288个样本。他们同时被存入保存最大数字的归档中。稍后会解释。样本间隔时间为300秒,也就是5分钟,这是一个好的开始。:
1个样本 “平均” 保留5分钟的周期
6个样本 每30分钟进行一次平均
24个样本 每2小时进行一次平均
288个样本 每1天进行一次平均
 我们试着与MRTG互相兼容,MRTG存储以下数据::
600 5分钟样本数: 2天和2小时
600 30分钟样本数: 12.5天
600 2小时样本数: 50天
732 1天样本数:   732天
    这些范围被补充进去,因此在数据库中保存的数据总数大约797天。RRDtool存储不同的数据,它不会在每日归档停止的地方开始每周 归档。对于这两个归档,最新的数据会是在 now 附近,因此我们需要比MRTG保存更多的数据!
我们需要::
600个5分钟的样本 (2天和2小时)
700个30分钟的样本 (2天和2小时,加12.5天)
775个2小时的样本 (上述+50天)
797个1天的样本  (上述+732天,环型回绕最大797)
rrdtool create myrouter.rrd       
        DS:input:COUNTER:600:U:U 
        DS:output:COUNTER:600:U:U
        RRA:AVERAGE:0.5:1:600    
        RRA:AVERAGE:0.5:6:700    
        RRA:AVERAGE:0.5:24:775   
        RRA:AVERAGE:0.5:288:797  
        RRA:MAX:0.5:1:600        
        RRA:MAX:0.5:6:700        
        RRA:MAX:0.5:24:775       
        RRA:MAX:0.5:288:797
    接下来要做的就是收集数据并把它保存起来。以下是一个例子。它是用伪码写的,你得根据OS调整后让它能够运行。:
while not the end of the universe
do
   get result of
      snmpget router community 2.2.1.10.4
   into variable $in
   get result of
      snmpget router community 2.2.1.16.4
   into variable $out
rrdtool update myrouter.rrd N:$in:$out
wait for 5 minutes
done
Then, after collecting data for a day, try to create an image using:
在收集了1天的数据后,试着用下面的命令创建图像::
rrdtool graph myrouter-day.png --start -86400
         DEF:inoctets=myrouter.rrd:input:AVERAGE
         DEF:outoctets=myrouter.rrd:output:AVERAGE
         AREA:inoctets#00FF00:"In traffic"
         LINE1:outoctets#0000FF:"Out traffic"
     这会产生一个具有1天流量值的图像。1天有24(小时)x60(分钟)x60(秒)。我们从当前时间-86400秒开始。我们用DEF把输入和输出字节数定义成myrouter.rrd数据库中的的平均值,并且绘制输入流量区和输出流量线。