RRDtool

作为一个合格的运维工程师,监控技能必须是要掌握的,当然监控的软件很多很多(cacti,nagios,zabbix...)。而生产环境中一般只运用1、2种而已。所以全部掌握这些有点不靠谱。所以选择其中一种掌握之即可,当工作环境变化后还可以以之为跳板进行别的监控的学习。。。

笔者不记得什么时候收集的rrdtool的用法了,所以参考的地址也不能贴出来了。忘原作者看到相似的地方见谅。

笔者老师为马哥教育的马老师。这篇文章也参考了其讲课视频。大家可以通过链接到马哥那观看其cacti视频。


一、建立RRD数据库(.rrd文件)

rrdtool [options] command command_options

而commands包括:

create, update, updatev, graph, dump, restore,last, first, info, fetch, tune, resize, xport

这一讲我们将着重介绍一下creat命令的使用

1
2
3
4
5
6
rrdtool create filename
[--start|-b start time]
[--step|-s step]
[DS:ds-name:DST:heartbeat:min:max]
// DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max
[RRA:CF:xff:steps:rows]

我们用一个例子对整个语法进行解释(以下都用这个例子说明参数的使用):

1
2
3
4
5
6
rrdtool create target.rrd
--start 1023654125
--step 300
DS:mem:GAUGE:600:0:671744
RRA:AVERAGE:0.5:12:24
RRA:AVERAGE:0.5:288:31

简单的先说吧:

create 很容易理解,就是创建一个新的Round Robin Database (RRD) 数据库文件以存储信息。

filename习惯上会以 .rrd 结尾,请记住这个数据库文件的名字。

--start 这个参数可以指定 filename 的数据记录起始日期,你可以指定为 1970 年至今的秒数(参数为-b `date -d "1970/01/01" +%s`),如果你不指定,那么起始时间默认就是现在。

--step 采集数据的间隔时间,习惯上我们会设 300 (秒),当然你可以自行调整,这也是RRD的优势所在。但是采集周期不应该过短也不应小于你的update rrd文件周期,否则可能会造成服务器负载过重。

后面两个参数需要慢慢理解,我把语法和例子拿下来对比一下,大家就可能明白了。

[DS:ds-name:DST:heartbeat:min:max]

// DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max

对比例子

DS:mem:GAUGE:600:0:671744

下面以例子来说明:

DS:用来声明数据源的,也可以理解为声明数据变量的关键字。这个是必须写的,不能按照你的意愿修改成其他表述方式。

DS-NAME:变量名,可以理解为你给这个数据源起的助记符(简称DSN)。当每一个刷新周期到来的时候,数据文档中各变量对应的值就会被更新。这个变量对应的值在官方文档中也叫做主要数据点――PDP(Primary Data Point)。

DST:DS的类型,通常有:GAUGE, COUNTER, DERIVE, 和ABSOLUTE 四种,下面依次介绍:

GAUGE:

我们用的最多的就是GAUGE了,它的中文解释是:测量。在这里它表示实际的值。比如说输入次序为98 100 98,那么输出顺序也是98 100 98。

COUNTER:

累计值,自己进行计算,比如说输入次序为98 100 98,那么输出顺序也是2 -2,怎么出来的这两个数值呢?100-98 98-100,其实就是两个差值,它表示的是经过一个刷新周期的变化率。

DERIVE:

也是累计值,和COUNTER一样的,唯一不同的是它不存在负值,最小的是0,不如-2那么它就只划0,结果为 2 0

ABSOLUTE:

如同COUNTER,但COUNTER可能overflow(数值过大),所以会取绝对值

补充:COUNTER/DERIVE/AVSOLVTE 虽然都是取差值,但会再除以两次间隔间的秒数。

例,两次间隔间为300秒,那画出来的就是 2/300,-2/300 的值

再给出一个例子帮助大家理解:

Values = 300, 600, 900, 1200 实际值输入值(每隔300S输入一个)

Step = 300 seconds 刷新周期

COUNTER DS = 1, 1, 1, 1 COUNTER定义的DS的值

DERIVE DS = 1, 1, 1, 1 DERIVE定义的DS的值

ABSOLUTE DS = 1, 2, 3, 4 ABSOLUTE定义的DS的值

GAUGE DS = 300, 600, 900, 1200 GAUGE定义的DS的值

heartbeat 心跳有效期

比如在例子中,我们定义了心跳有效时间是600秒,也就是两个刷新周期。举个例子,在12点的时候没有产生数据,那么前后300S(共600S)的平均值就 会绘成12点的值,但如果在两个刷新周期内,都没有接收到数据更新,那么这个时候,必须往数据文档中写入一个(UN)UNKNOWN值。这是  RRDTool的一个特别的地方。要知道MRTG在处理网络中断的时候,记录的是0值。这个0和UN还是有一定区别的。

min:max 记录数据的最小值和最大值

DS数值的有效范围,超出就是UN喽。也可以写成 U:U 代表不限范围。

小技巧:将数据源建立方式记为 "三文字,三数字"

DS讲完了就该讲RRA了,那么什么是RRA呢?

RRA: 更简单,它的作用就是定义更新的数据是如何记录的,RRA 即 Round Robin Archive,Archive是什么,存档。比如我们每5分钟 产生一条刷新的数据,那么一个小时就是12条。每天就是288条。这么庞大的数据量,一定不可能都存下来。肯定有一个合并(consolidate)数据 的方式,那么这个就是RRA的作用了。

下面具体介绍怎么应用RRA:

使用方法:RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows

RRA:用以声明RRAs的关键字

CF:consolidation function 合并方式,包含四类:

AVERAGE, MIN,MAX, LAST //平均值,最大值,最小值,最后一笔

上面说过了,经过一个刷新周期,会获得一个主数据点(PDP),将若干个PDPs使用合并方式(CF)合并后会产生一个合并数据点CDP(consolidated data point)。

xff:xfiles factor 和unkown数据有关,很多资料都取0.5

step:有step条PDP合并形成一条CDP

row:记录的合并数据点CDP条数

我们在例子中对RRA是这样定义的:

RRA:AVERAGE:0.5:12:24 //1天

RRA:AVERAGE:0.5:288:31 //1月

对于第一个RRA,12条的PDP(每经过一个刷新周期产生一个PDP)经过CFed(AVERAGE),也就是取平均值,产生一个CDP,24个  CDPs存档。我们一起来计算一下时间,如果一个周期是300秒,那么12个PDP的产生时间就是一个小时,也就是一个小时产生一个CDP。24个  CDPs时间就是一天。说明这条通过这条RRA,我们可以取得一天的数据值。一天后,又经过一个小时。就会产生第25条,那么如何记录这个第25条数据 呢?根据我们这个RRA的定义,它将会替代第一条CDP的位置。

实例(检测某核心交换的端口)(create_nic_7609.sh)

/usr/local/rrd/bin/rrdtool create /www/rrd/NIC_7609.rrd -s 300 \

DS:ifInOctets1:COUNTER:600:U:U \

DS:ifInOctets2:COUNTER:600:U:U \

DS:ifInOctets9:COUNTER:600:U:U \

DS:ifInOctets11:COUNTER:600:U:U \

DS:ifInOctets14:COUNTER:600:U:U \

DS:ifInOctets53:COUNTER:600:U:U \

DS:ifOutOctets1:COUNTER:600:U:U \

DS:ifOutOctets2:COUNTER:600:U:U \

DS:ifOutOctets9:COUNTER:600:U:U \

DS:ifOutOctets11:COUNTER:600:U:U \

DS:ifOutOctets14:COUNTER:600:U:U \

DS:ifOutOctets53:COUNTER:600:U:U \

RRA:AVERAGE:0.5:1:4800 \

RRA:AVERAGE:0.5:6:2400 \

RRA:AVERAGE:0.5:24:1200 \

RRA:AVERAGE:0.5:288:600 \

RRA:MAX:0.5:1:4800 \

RRA:MAX:0.5:6:2400 \

RRA:MAX:0.5:24:1200 \

RRA:MAX:0.5:288:600

我们举例来看

RRA:AVERAGE:0.5:1:603 \

RRA:AVERAGE:0.5:6:603 \

RRA:AVERAGE:0.5:24:603 \

RRA:AVERAGE:0.5:288:800 \

RRA:MAX:0.5:1:603 \

RRA:MAX:0.5:6:603 \

RRA:MAX:0.5:24:603 \

RRA:MAX:0.5:288:800

解释一下,首先你要记得step我们设置为300秒,那么

0.5:1:603

因为我们将step设置为300秒,若原计算时间点为12:00,记录时11:57:30~12:02:30的平均值为主,这个值若在此时间点內只有一笔资料的话,其意即是平均值,所以此一值即表共要记录几笔,603是指要存603笔,超过603筆,則最早一笔將被移出。

0.5:6:603 仅就6解释,取6笔资料(每笔为step值,在此意即5分钟)为平均值( 30 分钟), 存 603 笔

0.5:24:603 24 即2小时

0.5:288:800 288 即1天

请注意,不是0.5:1:603中的1 就是五分钟,这个是依据你的--step值而定,如果--step 3600,那0.5:6:603这一行就是六小 时合起來的平均值了。若将 AVERAGE 换成MIN/MAX 的意义则是取该时间点中 (如上例之5min/30min/2hr..)之最大值或最小 值,而通常在监测系统时最大值与平均值是比较有实际意义的。下面这个图来帮助你记忆。

RRA:MIN:0.5:1:600 \

RRA:MIN:0.5:6:700 \

RRA:MIN:0.5:24:775 \

RRA:MIN:0.5:288:797 //一般可按cacti标准取值


第二讲:rrd数据的更新(update)

在创建好文档后,我们要用程序定时更新数据文档(.rrd)然后才能根据数据文档画图。以采集核心交换流量为例,首先我们要抓到各端口的流量,可以通过  snmp协议来取得数据。如果你机器上没有snmp,那么安装最新的net-snmp包(PS:被监控端一般上安装的是net-snmp, 监控端安装的是net-snmp-utils,当然,如果你需要被监控端添加通知故障功能的话,也需要安装net-snmp),安装完成后测试snmp,在提示符下键入:

1
2
3
4
5
6
7
8
9
10
$ snmpwalk
No hostname specified.
Usage: snmpwalk [options...] <hostname> {<community>} [<objectID>]
UCD-snmp version: 5.1.2
-h thishelp message.
-H Display configuration file directives understood.
-V display version number.
-v 1|2c|3specifies snmp version to use.
SNMP Version 1or 2c specific
……

出现以上信息表示net-snmp安装成功。

snmp的使用:

# snmpwalk -v 2c 核心交换IP地址 设备的community_string OID

具体的snmp用法及系统默认的OID还有Shell文件的执行方法可参考 cacti 中文论坛 的相关文档,这里我就不废话了。我们这一讲将主要说说如何更新rrd文件信息。

语法:

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

例如:

$ rrdtool update tcpdump.rrd 1061811856:114:0:50:1199:0:821073

上面的 1061811856 即时间值,如果就是要现在的时间值,可以 N 代表,但要转换成秒值,通常我們都会用

$ timestamp=`date +%s `

来转现在秒数,如果是某些特定时间,则可以

$ timestamp=`date -d "2003/08/15 12:00" +%s`

后面跟着所有的更新的数据,按照DS定义的顺序用冒号格开。

关于更新的数据需要你写个小程式取数据,或用snmpget/snmpwalk抓资料来做rrdtool update,然后用crontab根据你在rrdtool create 时的step决定执行的时间点。这里就应该用到shell的知识了,最常见的就是用Shell的正则表达式过滤通过 snmp取得的信息

我们看到了,通过snmp取得的核心交换的信息是非常之多的,这些信息当然不可能都用到,我们要从中选取我们要的信息。我们使用正则表达式对字符流进行过滤并排列成我们需要的方式。

对于正则表达式,这里不做解释,大家可以通过参考一些书辅助一些例子学习。

我们要取得的是端口的流入和流出的数据,所以我们使用snmp中的两个选项:ifInOctets和ifOutOctets 。分别对应的是端口的流入流量和流出流量。

特别地,对于采集100M及其以下的端口流量,这两个参数是完全正确的,但是如果是1000M的端口,就会出现流量和实际值相差甚远。在查过很多资料后发 现,原因是这样方式的计数模式,计数字长为32bit,如果采集1000M端口数据会发生数据溢出。我们要使用64bit的字长来计数。所以我们应该选用 的OID参数为:ifHCInOctets和ifHCOutOctets。

让我们来看个例子

RRD_FILE=/www/rrd/NIC_7609.rrd (.rrd数据文档的位置)

sec=300 //睡眠时间,也就是采集周期

while [ 1 ] //用一个循环

do

rrd_data="" //下面实际用到的是正则表达式的串拼接

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCInOctets |grep ".*ifHCInOctets.1 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCInOctets |grep ".*ifHCInOctets.2 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCInOctets |grep ".*ifHCInOctets.9 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCInOctets |grep ".*ifHCInOctets.11 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCInOctets |grep ".*ifHCInOctets.14 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCInOctets |grep ".*ifHCInOctets.53 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCOutOctets |grep ".*ifHCOutOctets.1 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCOutOctets |grep ".*ifHCOutOctets.2 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCOutOctets |grep ".*ifHCOutOctets.9 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCOutOctets |grep ".*ifHCOutOctets.11 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCOutOctets |grep ".*ifHCOutOctets.14 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' ':'`

rrd_data =$rrd_data`snmpwalk -v 2c IP地址 -c snmp团体名  ifHCOutOctets |grep ".*ifHCOutOctets.53 = " | sed -e 's/.*: \(.*\)$/\1/'| tr '\n' '\0'`

now=`date +%s` //当前时间距离1970的秒数

/usr/local/rrd/bin/rrdtool update $RRD_FILE $now:${rrd_data} //调用更新指令

sh ./NIC_7609_Graph.sh //调用绘图脚本画图,下面一节就介绍

sleep $sec //休息,等待下一个周期的到来

done //循环体结束

[补充]如果你得到了如下提示:

IF-MIB::ifHCInOctets = No Such Object available on this agent at this OID

有可能你的网卡是100M,那么就用ifOutOctets来测试就可以了。


rrdtool第三讲:画图

画图的语法很多,我只把最有用的列出来,有兴趣的朋友可以到官方网站上去查Manual。

方法:rrdtool graph p_w_picpath-filename,参数介绍如下

p_w_picpath-filename:图的文件名,比如test.png等

[-s|--start seconds]:绘图起始时间,预设是一天前(-1d),可用-s `date …`来指定时间

[-e|--end time]:绘图结束时间, 预设是现在(now),除date 的应用外,可用 -e -1w 表示绘图的时间结束于一周前

[-t|--title title]:图上显示的标题

[-v|--vertical-label text]:Y轴上的说明文字

[-w|--width pixels]:绘图区域,画图区宽的大小

[-h|--height pixels]:绘图区域,画图区高的大小

-u:Y轴正值高度

-l:Y轴负值高度

--no-minor 不要副格线

DEF(Define):就是定义一个变量

语法:

DEF:vname=rrd_filename:DS_name:CF

用如下表示更清楚一些

DEF:vname=rrd_filename:DS_name:[AVERAGE|MAX..]

主要用处在于您要取出哪个 RRD 档案的 DSN 到这个 graph 來。

从上很容易看出,你要定义一个虚拟的变量,变量从(.rrd)数据文件中取得数据源(DS)经过数据合并(CF)后的数据。看到这里,大家应该知道,前面在定义文档中为什么有那么多的参数,其实都是为了绘图做准备的。

① vname:虚拟变量名,我们自己取的,以后还要用到。

② rrd_filename:DS_name:CF :数据文件(.rrd)的全路径->数据源变量->合并方法。

举个例子吧:DEF:in_bytes_1=$RRD_PATH:ifInOctets1:AVERAGE

然而,我们觉得光有记录的数据源变量还是不够的,我们希望这些数据源变量可以计算。比如我希望把某两个端口的流量加在一起作为一个变量画图,那么这是我们就需要CDEF

CDEF 一個虚拟的变数,其值为 DEF 的某些运算,语法如下:

语法:CDEF:vname=rpn-expression

先举一个例子,我们从例子中说明问题。我们取得某端口流入流量的字节数,我们希望画在图上的是bit为单位,很明显我们要将字节数乘以8。

例:

DEF:in_bytes_1=$RRD_PATH:ifInOctets1:AVERAGE           //这句刚刚说过了

CDEF:in_bits_1= 8,in_bytes_1,*        //将DEF中定义的in_bytes_1×8放在in_bits_1

很好理解吧?那为什么不写成in_bits_1= in_bytes_1* 8?现在我们回到语法解释:

rpn(Reverse Polish Notation)逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。那么什么是逆波兰表达式呢?逆波兰表达式又叫做后缀表达式。哈哈google吧。

正常的表达式 逆波兰表达式

a+b a,b,+

a+(b-c) a,b,c,-,+

a+(b-c)*d a,d,b,c,-,*,+

那么a=1+3 就写成 a=1,3 +了。

http=(smtp+http+telnet)/1024 写成什么呢?

http=1024,smtp,http,telnet,+,+,/

下面终于到画图了,最常用的是:线和区域。

从图中可以看出有两种表示流量的方式,流入用绿色的区域(AREA),流出用蓝色的线(LINE)。这就是画图的几个元素。我们还是先看一下语法。

AREA:vname[#rrggbb[:legend]]

LINE{1|2|3}:vname[#rrggbb[:legend]]

STACK:vname[#rrggbb[:legend]]

① vname:根据虚拟变量(vname)画图。

② #rrggbb:颜色的16进制表示,可以找个软件来看。

③ legend:对该颜色的提示,最后会写在图上的。

④ 特别的,画线有粗细之分,所以有LINE1-LINE3,line1最细,LINE3最粗。

⑤ AREA 可以画出资料数值至0之间的区块图

⑥ STACK 是表现在的图的值,叠在上一个值上

例子:

AREA:in_bits_1#00cc00: " Current In"

LINE1:out_bits_1#0000ff: " Current Out "

请注意,如果使用 AREA/STACK 则需特別注意图盖图的问题,一定要先画大的值, 再画小的值,才会有层次的效果,不然,最大的数据若最后画,你就看不到前面的值了,都被最后一个图给压过去了。

关于图下面的提示怎么画呢?我们必须使用这两条指令GPRINT和COMMENT

语法:

GPRINT:vname:CF:format

COMMENT:text

没有什么难点,有点像C语言的表达式,举两个例子大家就会很好理解的。例:

COMMENT: "Hello World .\c " 以居中的方式显示Hello world

GPRINT:in_bits_1:AVERAGE:"Average Current\:%8.2lf %S bps"

//显示in_bits_1的值,精确到小数点后面两位

这些说明性文字都可以用 \n 等换行符号

例如:

GPRINT:telnet:AVERAGE:"%10.0lf \n"

意即要输出这段时间中 (-s ~ -e 中,telnet的平均值,%10.0lf 则是为了好算位置)

例子1:

#tcpdump.sh

RRD_PATH="/root/study/tcpdump.rrd"

p_w_picpath_path="/root/study/html"

sec=300

killall tcpdump

mv ip.packet ip.packet.1

tcpdump -w ip.packet tcp or udp or icmp &

scan_port="23 25 53 80 110"

rrd_data=""

for sport in $scan_port

do

port=`tcpdump -r ip.packet.1 port $sport -v | sed -e 's/.*, len \(.*\))/

\1/g' | tr '\n' '+'`

port=`echo ${port}0| bc`

port=`expr $port / $sec`

rrd_data="$rrd_data$port:"

done

total=`tcpdump -r ip.packet.1 -v |grep -v 'config'| sed -e 's/.*, len \(.*\))/\

1/g' | tr '\n' '+'`

total=` echo ${total}0 | bc`

now=`date +%s`

echo "rrdtool update tcpdump.rrd $now:$rrd_data$total" >>tcpdump.cmd

rrdtool update tcpdump.rrd $now:$rrd_data$total

p_w_picpath_path=/home/httpd/html/enum/study

now=`date "+%Y/%m/%d %H:%M:%S"`

start_time=`date -d "2003/08/12 19:00" +%s`

time="hour day week month year"

for t in $time

do

/usr/local/bin/rrdtool graph $p_w_picpath_path/example-$t.png \

--title "本機重要 port 流量" \

DEF:t1=$RRD_PATH:telnet:AVERAGE \

DEF:t2=$RRD_PATH:smtp:AVERAGE \

DEF:t3=$RRD_PATH:domain:AVERAGE \

DEF:t4=$RRD_PATH:http:AVERAGE \

DEF:t5=$RRD_PATH:total:AVERAGE \

CDEF:v1=t1,t2,t3,t4,+,+,+ \

CDEF:v2=t1,t2,t3,+,+ \

CDEF:v3=t1,t2,+ \

CDEF:v4=t1 \

CDEF:v5=t5,1024,/ \

COMMENT:"各 PORT 流量统计---最大------平均-------最小-------?#123;在\n" \

AREA:v1#339966:"HTTP" \

GPRINT:t4:MAX:" %12.0lf " \

GPRINT:t4:AVERAGE:"%12.0lf " \

GPRINT:t4:MIN:"%12.0lf " \

GPRINT:t4:LAST:"%12.0lf \n" \

AREA:v2#ffff00:"DNS" \

GPRINT:t3:MAX:" %12.0lf " \

GPRINT:t3:AVERAGE:"%12.0lf " \

GPRINT:t3:MIN:"%12.0lf " \

GPRINT:t3:LAST:"%12.0lf \n" \

AREA:v3#FF0000:"SMTP" \

GPRINT:t2:MAX:" %12.0lf " \

GPRINT:t2:AVERAGE:"%12.0lf " \

GPRINT:t2:MIN:"%12.0lf " \

GPRINT:t2:LAST:"%12.0lf \n" \

AREA:v4#0000ff:"TELNET" \

GPRINT:t1:MAX:" %12.0lf " \

GPRINT:t1:AVERAGE:"%12.0lf " \

GPRINT:t1:MIN:"%12.0lf " \

GPRINT:t1:LAST:"%12.0lf \n" \

LINE2:v5#000000:"全部(Kb)" \

GPRINT:v5:MAX:" %12.0lf " \

GPRINT:v5:AVERAGE:"%12.0lf " \

GPRINT:v5:MIN:"%12.0lf " \

GPRINT:v5:LAST:"%12.0lf \n" \

COMMENT:"\n" \

COMMENT:"\n" \

COMMENT:" Last Updated: $now" \

-v "per second (bytes)" -M -U 10 \

-Y -X b -h 200 -w 480 -s `date -d "-1 $t" +%s`

done

例子2(NIC_7609_Graph.sh):

绘图的时候,我们还特别画出了采集端口的日流量、周流量、月流量和年流量。配合Shell脚本的使用,可以达到很好的效果。

p_w_picpath_path=/www/web/nicp_w_picpaths

RRD_PATH=/www/rrd/FJNUNIC_7609.rrd

port="1 2 9 11 14 53" #端口列表

for p in $port #对每个端口的循环

do

DEFin="DEF:in_bytes_$p=$RRD_PATH:ifInOctets$p:AVERAGE"

DEFout="DEF:out_bytes_$p=$RRD_PATH:ifOutOctets$p:AVERAGE"

CDEF="CDEF:in_bits_$p=8,in_bytes_$p,* CDEF:out_bits_$p=8,out_bytes_$p,*"

ddate=`date` #取得当前日期

#以下流入

DRAW_IN="COMMENT:\"Last updated time : $ddate\c\"" #最后更新

DRAW_IN="${DRAW_IN} COMMENT:\"\n\"" #换行

DRAW_IN="${DRAW_IN} AREA:in_bits_$p#00cc00:\" Current In \n\" " #流入流量

DRAW_IN="${DRAW_IN} COMMENT:\" \" GPRINT:in_bits_$p:LAST:\"Last Current\:%.2lf%S bps\"" #流入当前流量文字提示

DRAW_IN="${DRAW_IN}GPRINT:in_bits_$p:AVERAGE:\"Average Current\:%.2lf%S bps\"" #流入平均流量文字提示

DRAW_IN="${DRAW_IN} GPRINT:in_bits_$p:MAX:\"Max Current\:%.2lf%S bps\n\""

#流入最大流量文字提示

#以下流出

DRAW_OUT="LINE1:out_bits_$p#0000ff:\" Current Out\n\" " #流出流量

DRAW_OUT="${DRAW_OUT}COMMENT:\" \" GPRINT:out_bits_$p:LAST:\"Last Current\:%.2lf%S bps\"" #流出当前流量文字提示

DRAW_OUT="${DRAW_OUT}GPRINT:out_bits_$p:AVERAGE:\"Average Current\:%.2lf%S bps\"" #流出平均流量文字提示

DRAW_OUT="${DRAW_OUT} GPRINT:out_bits_$p:MAX:\"Max Current\:%.2lf%S bps\n\"" #流出最大流量文字提示

ttime="d w m y" #时间列表;d日;w周;m月;y年

for t in $ttime #对每个时间循环

do

sec=`date -v-1$t +%s` #绘图起始时间的确定

cmd="/usr/local/rrd/bin/rrdtool graph \

$p_w_picpath_path/FJNUNIC_7609_IF${p}_${t}.png \

--title '${ttitle}' \

-v ' Bits Per Second' \

-s $sec \

-l 0 -h 150 -w 500 $DEFin $DEFout $CDEF $DRAW_IN $DRAW_OUT

--color CANVAS#ffffff

--color BACK#ffffff \

--color FONT#000000 \

--color MGRID#80C080 \

--color GRID#808020 \

--color FRAME#808080 \

--color ARROW#ff0000 \

--color SHADEA#404040 \

--color SHADEB#404040"

eval $cmd # 执行画图

done #时间循环结束

done #端口循环结束

转载于:https://blog.51cto.com/liyanxin/1342837

监控cacti中的RRDtool用法详解相关推荐

  1. C++中substr()函数用法详解

    C++中substr()函数用法详解 原型: string substr (size_t pos = 0, size_t len = npos) const; 返回一个新构造的string对象,其值初 ...

  2. c++中vector的用法详解

    c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间 ...

  3. C#中NameValueCollection类用法详解

    C#中NameValueCollection类用法详解,1.NameValueCollection类集合是基于 NameObjectCollectionBase 类. 但与 NameObjectCol ...

  4. c++ memset 语言_C++中memset函数用法详解

    本文实例讲述了C++中memset函数用法.分享给大家供大家参考,具体如下: 功 能: 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,块的大小由第三个参数指定,这个函数通常 ...

  5. python中的super用法详解_【Python】【类】super用法详解

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1: 代码段1: class A: def __init__(sel ...

  6. JSP 中EL表达式用法详解

    EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${ ...

  7. java中throws用法_java中throws实例用法详解

    在程序出现异常时,会有一个抛出异常的throw出现,这里我们要跟今天所讲的throws区分开.throws的作用是声明抛出,在名称上也跟throw有所不同.下面我们就throws对策概念.语法.实例带 ...

  8. python中的super用法详解_Python中super函数用法实例分析

    本文实例讲述了python中super函数用法.分享给大家供大家参考,具体如下: 这是个高大上的函数,在python装13手册里面介绍过多使用可显得自己是高手 23333. 但其实他还是很重要的. 简 ...

  9. STL 中map的用法详解

    STL 中map的用法详解 Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可 ...

最新文章

  1. 在Ubuntu 16.0.4.5 LTS上安装python 2.7版本的cv2模块
  2. 使用MySQL的geometry类型处理经纬度距离问题
  3. (转载)虚幻引擎3--【UnrealScript教程】章节一:8.Enums
  4. Python中两种文件修改的方式
  5. 六、乘胜追击,将剩下的Git知识点搞定
  6. Quartus ii与Modelsim-altera 6.5b联调前仿真
  7. 国内是否可以安装alexa_Alexa可以听到您无法听到的命令,哪些黑客可以利用
  8. 幼儿园管理系统的设计与实现
  9. Proteus —— 电路仿真软件
  10. sparksql 与flinksql 建表 与 连表记录
  11. 案例|工业物联网解决方案•生产数据可视化
  12. 找不到设备 将计算机连接到USB打印机,打印机连接电脑没反应怎么办
  13. 华为畅享20为什么没有计算机,华为畅享20有没有红外线?华为畅享20有NFC功能吗...
  14. 站在讲台上的时候,我怕我会心虚
  15. 怎么绑定虚拟服务器,虚拟服务器里怎样绑定ip地址
  16. 维修服务器的请示,关于更换云服务器的请示
  17. MSP430单片机GPIO编程入门教程
  18. 简述适配器的概念、作用以及主机适配器的概念
  19. 第一章恶意软件静态分析基础
  20. sys不能远程登录的问题

热门文章

  1. 算法题11 字符串的所有对称子串
  2. STM32使用IIC总线通讯协议在OLED屏幕上显示字符串、汉字、图像(硬件IIC)
  3. hive建立内部表映射hbase_快手 HBase 在千亿级用户特征数据分析中的应用与实践...
  4. 网络知识:路由器要不要每天重启?很多人都做错了,难怪网速慢
  5. 关于HTTPS的七个误解
  6. 华为发布岳云鹏手机_刚刚,华为发布鸿蒙2.0!手机可用!
  7. linux关机时循环输出脚本,Linux关机时执行指定脚本功能实现
  8. Android 第二课 Intent
  9. sketch钢笔工具_设计工具(Sketch,Adobe XD,Figma和InVision Studio)中奇怪的一项功能
  10. 细说 Vue.js 3.2 关于响应式部分的优化