Chinaunix首页 | 论坛 | 博客
  • 博客访问: 96937
  • 博文数量: 34
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 350
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-04 22:47
文章分类

全部博文(34)

文章存档

2017年(34)

我的朋友

分类: 服务器与存储

2017-03-08 07:41:01

一、snmp

简单网络管理协议(SNMP)
是TCP/IP协议簇的一个应用层协议。在1988年被制定,并被Internet体系结构委员会(IAB)采纳作为一个短期的网络管理解决方案;由于SNMP的简单性,在Internet时代得到了蓬勃的发展,1992年发布了SNMPv2版本,以增强SNMPv1的安全性和功能。现在,已经有了SNMPv3版本。

一套完整的SNMP系统主要包括管理信息库(MIB)、管理信息结构(SMI)及SNMP报文协议。

(1)管理信息库MIB:任何一个被管理的资源都表示成一个对象,称为被管理的对象。MIB是被管理对象的集合。它定义了被管理对象的一系列属性:对象的名称、对象的访问权限和对象的数据类型等。每个SNMP设备(Agent)都有自己的MIB。MIB也可以看作是NMS(网管系统)和Agent之间的沟通桥梁。它们之间的关系如图1所示。


MIB文件中的变量使用的名字取自ISO和ITU管理的对象标识符(object identifier)名字空间。它是一种分级树的结构。如图2所示,第一级有三个节点:ccitt、iso、iso-ccitt。低级的对象ID分别由相关组织分配。一个特定对象的标识符可通过由根到该对象的路径获得。一般网络设备取iso节点下的对象内容。如名字空间ip结点下一个名字为ipInReceives的MIB变量被指派数字值3,因而该变量的名字为:

 iso.org.dod.internet.mgmt.mib.ip.ipInReceives

相应的数字表示(对象标识符OID,唯一标识一个MIB对象)为:

1.3.6.1.2.1.4.3


当网络管理协议在报文中使用MIB变量时,每个变量名后还要加一个后缀,以作为该变量的一个实例。如ipInReceives的实例数字表示为:1.3.6.1.2.1.4.3.0.

需要注意的是,MIB中的管理对象的OID有些需要动态确定,如IP路由表,为了指明地址202.120.86.71的下一站路由(next hop),我们可以引用这样的实例:

iso.org.dod.internet.mgmt.mib.ip. ipRouteTable.ipRouteEntry.ipRouteNextHop.202.120.86.71, 相应的数字表示为:1.3.6.1.2.1.4.21.1.7.202.120.86.71

对于这种动态对象标识的实例,由于无法转换为预先指定的Readkey名称,与飞邻的产品冲突(需要动态生成可变Readkey),暂不考虑支持。


(2)管理信息结构(SMI)

SMI定义了SNMP框架所用信息的组织、组成和标识,它还为描述MIB对象和描述协议怎样交换信息奠定了基础。

SMI定义的数据类型:

◆ 简单类型(simple)

Integer:整型是-2,147,483,648~2,147,483,647的有符号整数

octet string: 字符串是0~65535个字节的有序序列

OBJECT IDENTIFIER: 来自按照ASN.1规则分配的对象标识符集

◆    简单结构类型(simple-constructed)

SEQUENCE 用于列表。这一数据类型与大多数程序设计语言中的“structure”类似。一个SEQUENCE包括0个或更多元素,每一个元素又是另一个ASN.1数据类型

 SEQUENCE OF type 用于表格。这一数据类型与大多数程序设计语言中的“array”类似。一个表格包括0个或更多元素,每一个元素又是另一个ASN.1数据类型。

◆    应用类型(application-wide)

IpAddress: 以网络序表示的IP地址。因为它是一个32位的值,所以定义为4个字节;

counter:计数器是一个非负的整数,它递增至最大值,而后回零。在SNMPv1中定义的计数器是32位的,即最大值为4,294,967,295;

Gauge :也是一个非负整数,它可以递增或递减,但达到最大值时保持在最大值,最大值为232-1;

time ticks:是一个时间单位,表示以0.01秒为单位计算的时间;


SNMP报文

SNMP报文结构如下:(编码之前)

版本号

团体名

协议数据单元PDU

SNMP共有5种报文,所以其PDU也有5中,第七点会详细介绍SNMP的5种协议数据单元。

SNMP的5种协议数据单元

SNMP规定了5种数据单元PDU(也就是SNMP报文),用来在管理进程和代理之间的交换。

get-request操作:从代理进程处提取一个或多个参数值。

get-next-request操作:从代理进程处提取紧跟当前参数值的下一个参数值。

set-request操作:设置代理进程的一个或多个参数值。

get-response操作:返回的一个或多个参数值。这个操作是由代理进程发出的,它是前面三种操作的响应操作。trap操作:代理进程主动发出的报文,通知管理进程有某些事情发生。
前面的3种操作是由管理进程向代理进程发出的,后面的2个操作是代理进程发给管理进程的,为了简化起见,前面3个操作今后叫做get、get-next和set操作。图1描述了SNMP的这5种报文操作。请注意,在代理进程端是用熟知端口161俩接收get或set报文,而在管理进程端是用熟知端口162来接收trap报文。

snmp报文转发流程

图1 SNMP的5种报文操作

图2是封装成UDP数据报的5种操作的SNMP报文格式。可见一个SNMP报文共有三个部分组成,即公共SNMP首部、get/set首部、trap首部、变量绑定。

snmp报文格式PDU

(1)公共SNMP首部
共三个字段:
版本 
写入版本字段的是版本号减1,对于SNMP(即SNMPV1)则应写入0。
共同体(community)
共同体就是一个字符串,作为管理进程和代理进程之间的明文口令,常用的是6个字符“public”。
PDU类型
根据PDU的类型,填入0~4中的一个数字,其对应关系如表2所示意图。

表2 PDU类型


PDU类型

名称

0

get-request

1

get-next-request

2

get-response

3

set-request

4

trap

(2)get/set首部
请求标识符(request ID)
这是由管理进程设置的一个整数值。代理进程在发送get-response报文时也要返回此请求标识符。管理进程可同时向许多代理发出get报文,这些报文都使用UDP传送,先发送的有可能后到达。设置了请求标识符可使管理进程能够识别返回的响应报文对于哪一个请求报文
差错状态(error status)
由代理进程回答时填入0~5中的一个数字,见表3的描述

表3 差错状态描述

差错状态

名字

说明

0

noError

一切正常

1

tooBig

代理无法将回答装入到一个SNMP报文之中

2

noSuchName

操作指明了一个不存在的变量

3

badValue

一个set操作指明了一个无效值或无效语法

4

readOnly

管理进程试图修改一个只读变量

5

genErr

某些其他的差错

差错索引(error index)
当出现noSuchName、badValue或readOnly的差错时,由代理进程在回答时设置的一个整数,它指明有差错的变量在变量列表中的偏移。
(3)trap首部
企业(enterprise)
填入trap报文的网络设备的对象标识符。此对象标识符肯定是在图3的对象命名树上的enterprise结点{1.3.6.1.4.1}下面的一棵子树上。
trap类型

此字段正式的名称是generic-trap,共分为表4中的7种。


trap类型

名字

说明

0

coldStart

代理进行了初始化

1

warmStart

代理进行了重新初始化

2

linkDown

一个接口从工作状态变为故障状态

3

linkUp

一个接口从故障状态变为工作状态

4

authenticationFailure

从SNMP管理进程接收到具有一个无效共同体的报文

5

egpNeighborLoss

一个EGP相邻路由器变为故障状态

6

enterpriseSpecific

代理自定义的事件,需要用后面的“特定代码”来指明



当使用上述类型2、3、5时,在报文后面变量部分的第一个变量应标识响应的接口。
特定代码(specific-code)
指明代理自定义的时间(若trap类型为6),否则为0。
时间戳(timestamp)
指明自代理进程初始化到trap报告的事件发生所经历的时间,单位为10ms。例如时间戳为1908表明在代理初始化后1908ms发生了该时间。
(4)变量绑定(variable-bindings)
指明一个或多个变量的名和对应的值。在get或get-next报文中,变量的值应忽略。


管理变量的表示

管理变量表示管理对象类型在某一时刻的值(或称该类型的实例),SNMP以管理变量作为操作对象。

管理变量的表示方法是这样规定的:形如x.y,其中x是管理对象的object identifer。y是能唯一确定对象类型值的一组数字,在非表型变量中为0,在表型变量中是这个表的索引,比如接口表中的接口号,或路由表中的目的网络地址等等 。如:在MIB文件里定义了ipAdEntNetMask这一管理对象,其object identifier为1.3.6.1.1.5.6.1.3它是个路由表中的一项,它的一个实例就是路由表中某一行的子网掩码,如果这行的索引、目的网络地址为129.102.1.0。则这个变量名是:1.3.6.1.1.5.6.1.3.129.102.1.0。在以后的说明中,为了方便,把唯一确定管理变量的一组数字,也就是x.y中的y称作实例。

SNMP的运行过程

驻留在被管设备上的AGENT从UDP端口161接受来自网管站的串行化报文,经解码、团体名验证、分析得到管理变量在MIB树中对应的节点,从相应的模块中得到管理变量的值,再形成响应报文,编码发送回网管站。网管站得到响应报文后,再经同样的处理,最终显示结果。

下面根据RFC1157详细介绍Agent接受到报文后采取的动作:

首先解码生成用内部表示的报文,解码依据ASN.1的基本编码规则,如果在此过程中出现错误导致解码失败则丢弃该报文,不做进一步处理。

第二步:将报文中的版本号取出,如果与本Agent支持的SNMP版本不一致,则丢弃该报文,不做进一步处理。当前北研的数据通信产品只支持SNMP版本1。

第三步:将报文中的团体名取出,此团体名由发出请求的网管站填写。如与本设备认可的团体名不符,则丢弃该报文,不做进一步处理,同时产生一个陷阱报文。SNMPv1只提供了较弱的安全措施,在版本3中这一功能将大大加强。

第四步:从通过验证的ASN.1对象中提出协议数据单元PDU,如果失败,丢弃报文,不做进一不处理。否则处理PDU,结果将产生一个报文,该报文的发送目的地址应同收到报文的源地址一致。

根据不同的PDU,SNMP协议实体将做不同的处理:

1.1 GetRequest PDU

第一种情况:如果PDU中的变量名在本地维护的MIB树中不存在,则接受到这个PDU的协议实体将向发出者发送一个GetResponse报文,其中的PDU与源PDU只有一点不同:将ERROR-STATUS置为noSuchName,并在ERROR-INDEX中指出产生该变量在变量LIST中的位置。

第二种情况:如果本地协议实体将产生的响应报文的长度大于本地长度限制,将向该PDU的发出者发送一个GetResponse报文,该PDU除了ERROR-STATUS置为tooBig,ERROR-INDEX置为0以外,与源PDU相同。

第三种情况:如果本地协议实体因为其他原因不能产生正确的响应报文,将向该PDU的发出者发送一个GetResponse报文,该PDU除了ERROR-STATUS置为genErr,ERROR-INDEX置为出错变量在变量LIST中的位置,其余与源PDU相同。

第四中情况:如果上面的情况都没有发生,则本地协议实体向该PDU的发出者发送一个GetResponse报文,该PDU中将包含变量名和相应值的对偶表,ERROR-STATUS为noError,ERROR-INDEX为0,request-id域的值应与收到PDU的request-id相同。

1.2 GetNextRequest PDU

GetNextRequest PDU的最重要的功能是表的遍历,这种操作受到了前面所说的管理变量的表示方法的支持,从而可以访问一组相关的变量,就好象他们在一个表内。

下面通过一个例子解释表遍历的过程:

被管设备维护如下路由表:

Destination NextHop Metric

10.0.0.99 89.1.1.42 5

9.1.2.3 99.0.0.3 3

10.0.0.51 89.1.1.42 5

假设网管站欲取得这张路由表的信息,该表的索引是目的网络地址。

网管站向被管设备发送一个GetNextRequest PDU,其中的受管对象的标识如下

GetNextRequest ( ipRouteDest, ipRouteNextHop, ipRouteMetric1 )

SNMP agent响应如下GetResponse PDU:

GetResponse (( ipRouteDest.9.1.2.3 = "9.1.2.3" ),

( ipRouteNextHop.9.1.2.3 = "99.0.0.3" ),

( ipRouteMetric1.9.1.2.3 = 3 ))

网管站继续:

GetNextRequest ( ipRouteDest.9.1.2.3,

ipRouteNextHop.9.1.2.3,

ipRouteMetric1.9.1.2.3 )

agent响应:

GetResponse (( ipRouteDest.10.0.0.51 = "10.0.0.51" ),

( ipRouteNextHop.10.0.0.51 = "89.1.1.42" ),

( ipRouteMetric1.10.0.0.51 = 5 ))

值得注意的是agent必须能够确定下一个管理变量名,以保证所有变量能被取到且只被取到一次。

网管站继续:

GetNextRequest ( ipRouteDest.10.0.0.51,

ipRouteNextHop.10.0.0.51,

ipRouteMetric1.10.0.0.51 )

agent 响应:

GetResponse (( ipRouteDest.10.0.0.99 = "10.0.0.99" ),

( ipRouteNextHop.10.0.0.99 = "89.1.1.42" ),

( ipRouteMetric1.10.0.0.99 = 5 ))

网管站继续

GetNextRequest ( ipRouteDest.10.0.0.99,

ipRouteNextHop.10.0.0.99,

ipRouteMetric1.10.0.0.99 )

这时因为路由表中所有的行都被取遍,agent因返回路由表对象的下一字典后继即该管理对象在MIB树中的后序遍历的直接后继。这里应是nettoMediaIndex,管理对象的OBJECT IDENTIFIER。这个响应通知网管站对表的遍历已经完成。

1.3 GetResponse PDU

GetResponse PDU只有当受到getRequest GetNextRequest SetRequest才由协议实体产生,网管站收到这个PDU后,应显示其结果。

1.4 SetRequest PDU

SetRequest PDU除了PDU类型标识以外,和GetRequest相同,当需要对被管变量进行写操作时,网管站侧的协议实体将生成该PDU。

对SetRequest的响应将根据下面情况分别处理:

如果是关于一个只读变量的设置请求,则收到该PDU的协议实体产生一个GetReponse报文,并置error status为noSuchName, error index的值是错误变量在变量list中的位置。

如果被管设备上的协议实体收到的PDU中的变量对偶中的值,类型、长度不符和要求,则收到该PDU的协议实体产生一个GetReponse报文,并置error status为badValue, error index的值是错误变量在变量list中的位置。

如果需要产生的GetReponse报文长度超过了本地限制,则收到该PDU的协议实体产生一个GetReponse报文,并置error status为tooBig, error index的值是0。

如果是其他原因导致SET失败,则收到该PDU的协议实体产生一个GetReponse报文,并置error status为genErr, error index的值是错误变量在变量list中的位置。

如果不符合上面任何情况,则agent将把管理变量设置收到的PDU中的相应值,这往往可以改变被管设备的运行状态。同时产生一个GetResponse PDU,其中error status置为noError,error index的值为0。

1.5 Trap PDU

Trap PDU的有如下的形式


产生trap的系统的OBJECT IDENTIFIER


系统的IP地址

普通类型

特定类型

时戳

变量对偶表


Trap是被管设备遇到紧急情况时主动向网管站发送的消息。网管站收到trap PDU后要将起变量对偶表中的内容显示出来。一些常用的trap类型有冷、热启动,链路状态发生变化等。



MIB:Management Information Base(管理信息库)
OID:对象标识符


MIB是将任何一个被监控对象它的名称和OID号之间的映射关系表

网络中监控实现的功能:

1、Fault Management(故障管理)

2、Configuration Management(配置管理)

3、Accounting Management(帐号管理)

4、Performance Management(性能管理)

5、Security Management(安全管理)


SNMP安装


1、安装snmp服务
[root@localhost ~]# yum install net-snmp net-snmp-utils

2、启动snmp服务
[root@localhost ~]# service snmpd start
正在启动 snmpd:                                           [确定]

3、查看监听的端口
[root@localhost ~]# ss -unlp
State       Recv-Q Send-Q                                          Local Address:Port                                            Peer Address:Port
UNCONN      0      0                                                           *:161                                                        *:*      users:(("snmpd",1321,8))
UNCONN      0      0                                                           *:68                                                         *:*      users:(("dhclient",943,5))

4、获取本地资源信息
[root@localhost ~]# snmpwalk -v 2c -c public localhost
SNMPv2-MIB::sysDescr.0 = STRING: Linux localhost.localdomain 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (27325) 0:04:33.25
SNMPv2-MIB::sysContact.0 = STRING: Root (configure /etc/snmp/snmp.local.conf)
SNMPv2-MIB::sysName.0 = STRING: localhost.localdomain
SNMPv2-MIB::sysLocation.0 = STRING: Unknown (edit /etc/snmp/snmpd.conf)
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORID.1 = OID: SNMP-MPD-MIB::snmpMPDMIBObjects.3.1.1
SNMPv2-MIB::sysORID.2 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
SNMPv2-MIB::sysORID.3 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance
SNMPv2-MIB::sysORID.4 = OID: SNMPv2-MIB::snmpMIB
SNMPv2-MIB::sysORID.5 = OID: TCP-MIB::tcpMIB
SNMPv2-MIB::sysORID.6 = OID: IP-MIB::ip
SNMPv2-MIB::sysORID.7 = OID: UDP-MIB::udpMIB
SNMPv2-MIB::sysORID.8 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup
SNMPv2-MIB::sysORDescr.1 = STRING: The MIB for Message Processing and Dispatching.
SNMPv2-MIB::sysORDescr.2 = STRING: The MIB for Message Processing and Dispatching.
SNMPv2-MIB::sysORDescr.3 = STRING: The SNMP Management Architecture MIB.
SNMPv2-MIB::sysORDescr.4 = STRING: The MIB module for SNMPv2 entities
SNMPv2-MIB::sysORDescr.5 = STRING: The MIB module for managing TCP implementations
SNMPv2-MIB::sysORDescr.6 = STRING: The MIB module for managing IP and ICMP implementations
SNMPv2-MIB::sysORDescr.7 = STRING: The MIB module for managing UDP implementations
SNMPv2-MIB::sysORDescr.8 = STRING: View-based Access Control Model for SNMP.
SNMPv2-MIB::sysORUpTime.1 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORUpTime.2 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORUpTime.3 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORUpTime.4 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORUpTime.5 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORUpTime.6 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORUpTime.7 = Timeticks: (5) 0:00:00.05
SNMPv2-MIB::sysORUpTime.8 = Timeticks: (5) 0:00:00.05
HOST-RESOURCES-MIB::hrSystemUptime.0 = Timeticks: (103588) 0:17:15.88
HOST-RESOURCES-MIB::hrSystemUptime.0 = No more variables left in this MIB View (It is past the end of the MIB tree)

5、获取MIB库信息
[root@localhost ~]# snmpget -v 2c -c public localhost HOST-RESOURCES-MIB::hrSystemUptime.0
HOST-RESOURCES-MIB::hrSystemUptime.0 = Timeticks: (147918) 0:24:39.18

6、查看mib库的信息文件
[root@localhost mibs]# cd /usr/share/snmp/mibs/
[root@localhost mibs]# ls
AGENTX-MIB.txt                       IF-INVERTED-STACK-MIB.txt  NET-SNMP-EXAMPLES-MIB.txt  SMUX-MIB.txt                 SNMPv2-TC.txt
BRIDGE-MIB.txt                       IF-MIB.txt                 NET-SNMP-EXTEND-MIB.txt    SNMP-COMMUNITY-MIB.txt       SNMPv2-TM.txt
DISMAN-EVENT-MIB.txt                 INET-ADDRESS-MIB.txt       NET-SNMP-MIB.txt           SNMP-FRAMEWORK-MIB.txt       SNMP-VIEW-BASED-ACM-MIB.txt
DISMAN-SCHEDULE-MIB.txt              IP-FORWARD-MIB.txt         NET-SNMP-PASS-MIB.txt      SNMP-MPD-MIB.txt             TCP-MIB.txt
DISMAN-SCRIPT-MIB.txt                IP-MIB.txt                 NET-SNMP-TC.txt            SNMP-NOTIFICATION-MIB.txt    TRANSPORT-ADDRESS-MIB.txt
EtherLike-MIB.txt                    IPV6-ICMP-MIB.txt          NET-SNMP-VACM-MIB.txt      SNMP-PROXY-MIB.txt           UCD-DEMO-MIB.txt
HCNUM-TC.txt                         IPV6-MIB.txt               NETWORK-SERVICES-MIB.txt   SNMP-TARGET-MIB.txt          UCD-DISKIO-MIB.txt
HOST-RESOURCES-MIB.txt               IPV6-TCP-MIB.txt           NOTIFICATION-LOG-MIB.txt   SNMP-USER-BASED-SM-MIB.txt   UCD-DLMOD-MIB.txt
HOST-RESOURCES-TYPES.txt             IPV6-TC.txt                RFC1155-SMI.txt            SNMP-USM-AES-MIB.txt         UCD-IPFWACC-MIB.txt
IANA-ADDRESS-FAMILY-NUMBERS-MIB.txt  IPV6-UDP-MIB.txt           RFC1213-MIB.txt            SNMP-USM-DH-OBJECTS-MIB.txt  UCD-SNMP-MIB.txt
IANAifType-MIB.txt                   LM-SENSORS-MIB.txt         RFC-1215.txt               SNMPv2-CONF.txt              UDP-MIB.txt
IANA-LANGUAGE-MIB.txt                MTA-MIB.txt                RMON-MIB.txt               SNMPv2-MIB.txt
IANA-RTPROTO-MIB.txt                 NET-SNMP-AGENT-MIB.txt     SCTP-MIB.txt               SNMPv2-SMI.txt

7、查看跟TCP相关的MIB文件
[root@localhost mibs]# vim TCP-MIB.txt


8、获取6资源的TCP信息,打开snmp的主配置文件snmpd.conf,
[root@localhost ~]# vim /etc/snmp/snmpd.conf
加入下图所示的一行:


9、重启服务
[root@localhost ~]# service snmpd restart
停止 snmpd:                                               [确定]
正在启动 snmpd:                                           [确定]

10、查看跟TCP相关的所有信息
[root@localhost ~]# snmpwalk -v 2c -c public localhost tcp
TCP-MIB::tcpRtoAlgorithm.0 = INTEGER: other(1)
TCP-MIB::tcpRtoMin.0 = INTEGER: 200 milliseconds
TCP-MIB::tcpRtoMax.0 = INTEGER: 120000 milliseconds
TCP-MIB::tcpMaxConn.0 = INTEGER: -1
TCP-MIB::tcpActiveOpens.0 = Counter32: 27
TCP-MIB::tcpPassiveOpens.0 = Counter32: 1
TCP-MIB::tcpAttemptFails.0 = Counter32: 0
TCP-MIB::tcpEstabResets.0 = Counter32: 0
TCP-MIB::tcpCurrEstab.0 = Gauge32: 1
TCP-MIB::tcpInSegs.0 = Counter32: 7997
TCP-MIB::tcpOutSegs.0 = Counter32: 4438
TCP-MIB::tcpRetransSegs.0 = Counter32: 11
TCP-MIB::tcpConnState.0.0.0.0.22.0.0.0.0.0 = INTEGER: listen(2)
TCP-MIB::tcpConnState.127.0.0.1.25.0.0.0.0.0 = INTEGER: listen(2)
TCP-MIB::tcpConnState.127.0.0.1.199.0.0.0.0.0 = INTEGER: listen(2)
TCP-MIB::tcpConnState.127.0.0.1.6010.0.0.0.0.0 = INTEGER: listen(2)
TCP-MIB::tcpConnState.192.168.0.104.22.192.168.0.105.52513 = INTEGER: established(5)
TCP-MIB::tcpConnLocalAddress.0.0.0.0.22.0.0.0.0.0 = IpAddress: 0.0.0.0
TCP-MIB::tcpConnLocalAddress.127.0.0.1.25.0.0.0.0.0 = IpAddress: 127.0.0.1
TCP-MIB::tcpConnLocalAddress.127.0.0.1.199.0.0.0.0.0 = IpAddress: 127.0.0.1
TCP-MIB::tcpConnLocalAddress.127.0.0.1.6010.0.0.0.0.0 = IpAddress: 127.0.0.1
TCP-MIB::tcpConnLocalAddress.192.168.0.104.22.192.168.0.105.52513 = IpAddress: 192.168.0.104
TCP-MIB::tcpConnLocalPort.0.0.0.0.22.0.0.0.0.0 = INTEGER: 22
TCP-MIB::tcpConnLocalPort.127.0.0.1.25.0.0.0.0.0 = INTEGER: 25
TCP-MIB::tcpConnLocalPort.127.0.0.1.199.0.0.0.0.0 = INTEGER: 199
TCP-MIB::tcpConnLocalPort.127.0.0.1.6010.0.0.0.0.0 = INTEGER: 6010
TCP-MIB::tcpConnLocalPort.192.168.0.104.22.192.168.0.105.52513 = INTEGER: 22
TCP-MIB::tcpConnRemAddress.0.0.0.0.22.0.0.0.0.0 = IpAddress: 0.0.0.0
TCP-MIB::tcpConnRemAddress.127.0.0.1.25.0.0.0.0.0 = IpAddress: 0.0.0.0
TCP-MIB::tcpConnRemAddress.127.0.0.1.199.0.0.0.0.0 = IpAddress: 0.0.0.0
TCP-MIB::tcpConnRemAddress.127.0.0.1.6010.0.0.0.0.0 = IpAddress: 0.0.0.0
TCP-MIB::tcpConnRemAddress.192.168.0.104.22.192.168.0.105.52513 = IpAddress: 192.168.0.105
TCP-MIB::tcpConnRemPort.0.0.0.0.22.0.0.0.0.0 = INTEGER: 0
TCP-MIB::tcpConnRemPort.127.0.0.1.25.0.0.0.0.0 = INTEGER: 0
TCP-MIB::tcpConnRemPort.127.0.0.1.199.0.0.0.0.0 = INTEGER: 0
TCP-MIB::tcpConnRemPort.127.0.0.1.6010.0.0.0.0.0 = INTEGER: 0
TCP-MIB::tcpConnRemPort.192.168.0.104.22.192.168.0.105.52513 = INTEGER: 52513
TCP-MIB::tcpInErrs.0 = Counter32: 0
TCP-MIB::tcpOutRsts.0 = Counter32: 2
TCP-MIB::tcpConnectionState.ipv4."192.168.0.104".22.ipv4."192.168.0.105".52513 = INTEGER: established(5)
TCP-MIB::tcpConnectionProcess.ipv4."192.168.0.104".22.ipv4."192.168.0.105".52513 = Gauge32: 1258
TCP-MIB::tcpListenerProcess.ipv4."0.0.0.0".22 = Gauge32: 1058
TCP-MIB::tcpListenerProcess.ipv4."127.0.0.1".25 = Gauge32: 1134
TCP-MIB::tcpListenerProcess.ipv4."127.0.0.1".199 = Gauge32: 1367
TCP-MIB::tcpListenerProcess.ipv4."127.0.0.1".6010 = Gauge32: 1258
TCP-MIB::tcpListenerProcess.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00".22 = Gauge32: 1058
TCP-MIB::tcpListenerProcess.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01".25 = Gauge32: 1134
TCP-MIB::tcpListenerProcess.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01".6010 = Gauge32: 1258

11、查看已建立的TCP 链接
[root@localhost ~]# snmpwalk -v 2c -c public localhost tcp|grep established
TCP-MIB::tcpConnState.192.168.0.104.22.192.168.0.105.52513 = INTEGER: established(5)
TCP-MIB::tcpConnectionState.ipv4."192.168.0.104".22.ipv4."192.168.0.105".52513 = INTEGER: established(5)

12、修改默认资源的名称和密码,修改允许获取数据的主机和网段


13、重新启动snmp服务
[root@localhost ~]# service snmpd restart
停止 snmpd:                                               [确定]
正在启动 snmpd:                                           [确定]

14、查看机器打开的tcp链接
[root@localhost ~]# snmpnetstat -v 2c -c huaxia -Ca -Cp tcp 127.0.0.1
Active Internet (tcp) Connections (including servers)
Proto Local Address          Remote Address         (state)
tcp   *.ssh                  *.*                   LISTEN
tcp   localhost.smtp         *.*                   LISTEN
tcp   localhost.smux         *.*                   LISTEN
tcp   localhost.x11-ssh-     *.*                   LISTEN
tcp   192.168.0.104.ssh      192.168.0.105.52513   ESTABLISHED

15、把服务加入开机自启动
[root@localhost ~]# chkconfig snmpd on

二、rrdtool

1.概述

RRDtool 代表 “Round Robin Database tool” ,作者同时也是 MRTG 软件的发明人。官方站点位于。所 谓的“Round Robin” 其实是一种存储数据的方式,使用固定大小的空间来存储数据,并有一个指针指向最新的数据的位置。我们可以把用于存储数据的数据库的空间看成一个圆,上面有 很多刻度。这些刻度所在的位置就代表用于存储数据的地方。所谓指针,可以认为是从圆心指向这些刻度的一条直线。指针会随着数据的读写自动移动。要注意的 是,这个圆没有起点和终点,所以指针可以一直移动,而不用担心到达终点后就无法前进的问题。在一段时间后,当所有的空间都存满了数据,就又从头开始存放。 这样整个存储空间的大小就是一个固定的数值。所以RRDtool 就是使用类似的方式来存放数据的工具, RRDtool 所使用的数据库文件的后缀名是'.rrd。如下图,


2.特点

  • 首先 RRDtool 存储数据,扮演了一个后台工具的角色。但同时 RRDtool 又允许创建图表,这使得RRDtool看起来又像是前端工具。其他的数据库只能存储数据,不能创建图表。

  • RRDtool 的每个 rrd 文件的大小是固定的,而普通的数据库文件的大小是随着时间而增加的。

  • 其他数据库只是被动的接受数据, RRDtool 可以对收到的数据进行计算,例如前后两个数据的变化程度(rate of change),并存储该结果。

  • RRDtool 要求定时获取数据,其他数据库则没有该要求。如果在一个时间间隔内(heartbeat)没有收到值,则会用 UNKN (unknow)代替,其他数据库则不会这样。

3、配置epel的yum源,然后安装rrdtool

yum install rrdtool

4、rrdtool绘图步骤

步骤一︰建立RRD文件,这个文件说来就是RRDtool的专属数据库。RRDtool以自有的格式存放数据。下面会讲解!

步 骤二︰抓取数据个人觉得是整个RRDtool最困难的一部分,因为RRDtool的数据是要靠自己在创建RRD数据库时定义出来,不像MRTG内建抓数据 功能,但是却因为如此,可以给RRDtool画图的数据弹性也比较大,例如︰snmp查询结果、系统状态、网页中特定数据统计等等。

步骤三︰将抓下来的数据就用rrdtool update的指令进行更新到的RRD数据库中,让图表能画出最新的流量。

步骤四︰这就是重点啦!通过rrdtool graph的指令来依据RRD数据库的数据进行绘图,这也是使用者唯一看的到的东西,若规划的不好会影响使用者阅读上的困难!

循环︰由于要完成动态绘图的图表,第二步骤到第四步骤必须不断的重复执行以维持资料的更新,目前知道要达成循环的方法有两种︰

  • 在Script中使用循环

  • 使用crontab任务计划

5、rrdtool命令详解

创建RRD数据库

create 语法

rrdtool create filename
[--start|-b starttime]
[--step|-s step]
DS:ds-name:DST:dst arguments#最后获取的数据是PDP,更新数据时要考滤DS顺序(*把所有要更新的数据,按照DS定义的顺序用冒号格开*)
RRA:CF:cf arguments#最后获取的数据是CDP,绘图时使用的是这些数据


参数详解:

  • DS:DS 用于定义 Data Soure 。也就是用于存放结果的变量名。DS是用来申明数据源的,也可以理解为申明数据变量,也就是你要检测的端口对应的变量名,这个参数在画图的时候还要使用的。

  • DST:DST 就是DS的类型。有 COUNTER、GUAGE、DERIVE、ABSOLUTE、COMPUTE 5种。由于网卡流量属于计数器型,所以这里应该为 COUNTER 。

  • RRA:RRA 用于指定数据如何存放。我们可以把一个RRA 看成一个表,各保存不同 interval 的统计结果。RRA的作用就是定义更新的数据是如何记录的。比如我们每5分钟产生一条刷新的数据,那么一个小时就是12条。每天就是288条。这么庞大的 数据量,一定不可能都存下来。肯定有一个合并(consolidate)数据的方式,那么这个就是RRA的作用了。

  • PDP:Primary Data Point 。正常情况下每个 interval RRDtool 都会收到一个值;RRDtool 在收到脚本给来的值后会计算出另外一个值(例如平均值),这个 值就是 PDP ;这个值代表的一般是“xxx/秒”的含义。注意,该值不一定等于RRDtool 收到的那个值。除非是GAUGE ,可以看下面的例子就知道了

  • CF:CF 就是 Consolidation Function 的缩写。也就是合并(统计)功能。有 AVERAGE、MAX、MIN、LAST 四种分别表示对多个PDP 进行取平均、取最大值、取最小值、取当前值四种类型。具体作用等到 update 操作时再说。

  • CDP:Consolidation Data Point 。RRDtool 使用多个 PDP 合并为(计算出)一个 CDP。也就是执行上面 的CF 操作后的结果。这个值就是存入 RRA的数据,绘图时使用的也是这些数据

下面是RRA与PDP、CDP之间的关系图,



默认是以 .rrd 结尾,但也以随你设定。

(1).--start|-b start time

设 定RRD数据库加入的第一个数据值的时间,从1970-01-01 00:00:00 UTC时间以来的时间(秒)。RRDtool不会接受早于或在指定时刻上的任何数值。默认值是now-10s;如果 update 操作中给出的时间在 –-start 之前,则 RRDtool拒绝接受。--satrt 选项也是可选的。 如果你想指定--start 为1天前,可以用CODE:--start $(date -d '1 days ago' +%s)。注意,--start 选项的值必是 timestamp 的格式。


(2).--step|-s step

指定数据将要被填入RRD数据库的基本的时间间隔。默认值是300秒;


(3).DS:ds-name:DST:dst arguments DS(Data Source)

DS:DS 用于定义 Data Soure 。也就是用于存放结果的变量名。 DS是用来申明数据源的,也可以理解为申明数据变量,也就是你要检测的端口对应的变量名,这个参数在画图的时候还要使用的。这里开始定义RRD数据的基本 属性;单个RRD数据库可以接受来自几个数据源的输入。在DS选项中要为每个需要在RRD中存储的数据源指定一些基本的属性;ds-name数据域命 名;DST定义数据源的类型,dst arguments参数依赖于数据源的类型。


案例:DS:mysql:COUNTER:600:0:100000000

DS(Data Source,数据源)表达式总共有六个栏位:

  • DS 表示这个为DS表达式

  • ds-name 数据域命名

  • DST 定义数据源的类型

  • heartbeat 有效期(heartbeat),案例里的值为'600',假设要取12:00的数据,而前后300秒里的值(11:55-12:05)经过平均或是取最大或最小都算是12:00的有效值;

  • min 允许存放的最小值,此例允许最小为0。

  • max 允许存放的最大值,最大为100000000。

注,如果不想设限制可以再第五个栏位和第六个栏位以 "U:U"表示(U即Unknown)。


DST 定义数据源的类型。数据源项的后续参数依赖于数据源的类型。对于GAUGE、COUNTER、DERIVE、以及ABSOLUTE,其数据源的格式为: DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max。DST 的选择是十分重要的,如果选错了 DST ,即使你的脚本取的数据是对的,放入 RRDtool 后也是错误的,更不用提画出来的图是否有意义了。

  • GAUGE :GAGUE 和上面三种不同,它没有“平均”的概念,RRDtool 收到值之后字节存入 RRA 中。

  • COUNTER :必须是递增的,除非是计数器溢出。在这种情况下,RRDtool 会自动修改收到的值。例如网络接口流量、收到的packets 数量都属于这一类型。

  • DERIVE:和 COUNTER 类似。但可以是递增,也可以递减,或者一会增加一会儿减少。

  • ABSOLUTE :ABSOLUTE 比较特殊,它每次都假定前一个interval的值是0,再计算平均值。

  • COMPUTE :COMPUTE 比较特殊,它并不接受输入,它的定义是一个表达式,能够引用其他DS并自动计算出某个值。例如 CODE:DS:eth0_bytes:COUNTER:600:0:U DS:eth0_bits:COMPUTE:eth0_bytes,8,* 则 eth0_bytes 每得到一个值,eth0_bits 会自动计算出它的值:将 eth0_bytes 的值乘以 8 。不过 COMPUTE 型的 DS 有个限制,只能应用它所在的 RRD 的 DS ,不能引用其他 RRD 的 DS。 COMPUTE 型 DS 是新版本的 RRDtool 才有的,你也可以用 CDEF 来实现该功能。如:CDEF:eth0_bits=eth0_bytes,8,*


DST 实例说明,

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 不做运算,直接存入数据库。所以第一行的 values 并不是 PDP,后面4行才是PDP。


下面我们来建立一个RRD库文件
[root@localhost ~]# rrdtool create eth0.rrd \
> --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天

有的人可能会问,上面有两个 DS,那 RRA 中究竟存的是那个 DS 的数据呢?实际上,这些 RRA 是共用的,你只需建立一个 RRA,它就可以用于全部的 DS 。所以在定义 RRA 时不需要指定是给那个 DS 用的。

(4).RRA:CF:cf arguments

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


RRD 的一个目的是在一个环型数据归档中存储数据。一个归档有大量的数据值或者每个已定义的数据源的统计,而且它是在一个RRA行中被定义的。当一个数据进入 RRD数据库时,首先填入到用 -s 选项所定义的步长的时隙中的数据,就成为一个pdp值,称为首要数据点(Primary Data Point)。该数据也会被用该归档的CF归并函数进行处理。可以把各个PDPs通过某个聚合函数进行归并的归并函数有这样几种:AVERAGE、 MIN、MAX、LAST等。这些归并函数的RRA命令行格式为:RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows。

什么是 CF?

以上面的案例中第2个RRA 和 4,2,1,3 这4个 PDP 为例

  • AVERAGE :则结果为 (4+2+1+3)/4=2.5

  • MAX :结果为4个数中的最大值 4

  • MIN :结果为4个数中的最小值1

  • LAST :结果为4个数中的最后一个 3

同理,第三个RRA和第4个RRA则是每24个 PDP、每288个 PDP 合成为1个 CDP。


解释度(Resolution)

这 里要提到一个 Resolution 的概念,在官方文档中多处提到 resolution 一词。Resolution 究竟是什么?Resolutino 有什么用?举个例子,如果我们要绘制1小时的数据,也就是60分钟,那么我们可以从第一个RRA 中取出12个 CDP 来绘图;也可以从第2个 RRA中取出3个 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 中提到它。


xff 字段

细心的朋友可能会发现,在 RRA 的定义中有一个数值,固定是 0.5 ,这个到底是什么东东呢?
这个称为 xff 字段,是 xfile factor 的缩写。让我们来看它的定义 :

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)

这个看起来有点头晕,我们举个简单的例子 :例如

CODE:RRA:AVERAGE:0.5:24:600

这个 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 了。


2.抓取数据

简单说,就是用shell写个脚本去不断的收集数据。对于不懂shell编辑的博友可以去网上找点资料学习一下,很简单的。下面是利用snmp来获取进入网卡的流量。



[root@node1 ~]# snmpget -v 2c -c public 192.168。0.120 ifInOctets.2
IF-MIB::ifInOctets.2 = Counter32: 57266195

上 面的例子是使用snmpget来抓取192.168.18.201的网卡输入流量,-v 2c表示snmp版本号,-c public snmp共同体名称,192.168.0.120是这台主机的IP地址,ifInOctets.2是指eth0网卡的输入流 量,ifInOctets.1是指lo0网卡的输入流量。从上面我们可以看出,eth0输入的流量为57266195。下面我们来截取一下输入流量,



[root@node1 ~]# snmpget -v 2c -c public 192.168.0.120 ifInOctets.2 | sed -e 's/.*ter32: \(.*\)/\1/'
57463513

我们得到的值为57463513,这就是我们要的结果。我们只要用shell脚本写个循环就可以收集网卡的输入流量了,再用rrdtool update命令将收集到的数据更新到RRD数据库中即可。

当然,您不一定要使用snmpget,也可以使用snmpwalk、tcpdump等等抓取数据回来分析,说夸张点,凡是有变化的数据都可以经过处理变成我们要的资料,然后画成图表。


3.更新RRD数据库数据

update 语法





rrdtool update filename [--template|-t ds-name[:dsname]...] N|timestamp:value[:value...]
filename RRD数据库文件名称
--template|-t ds-name[:ds-name] 要更新RRD数据库中数据源的名称,其中-t指定数据源的顺序
N|timestamp:value[:value...] 时间:要更新的值

案例:



[root@node1 ~]#rrdtool update eth0.rrd 1381467942:60723022 或
[root@node1 ~]# rrdtool update eth0.rrd N:60723022

其中,1381467942是当前的时间戳,可以用date +%s命令获得,或者直接用N代替。60723022是当前要更新的流量数据,可以用shell脚本获得。下面我们来查看一下,更新的数据。


[root@node1 ~]# rrdtool fetch eth0.rrd AVERAGE


4.绘制图表

使用RRDtool 我们最关心什么?当然是把数据画出来了。虽然前面谈了很多,但这些都是基础来的。掌握好了,可以让你在绘图时更加得心应手。

graph 语法











rrdtool graph filename [option ...]
[data definition ...]
[data calculation ...]
[variable definition ...]
[graph element ...]
[print element ...]
其中的 data definiton、variable definition 、data calculation、分别是下面的格式,
DEF:=::[:step=][:start=
VDEF:vname=RPN expression
CDEF:vname=RPN expression

其中 filename 就是你想要生成的图片文件的名称,默认是 png 。你可以通过选项修改图片的类型,可以有 PNG、SVG、EPS、PDF四种。

(1).DEF 是 Definition (定义)的意思。定义什么呢?你要绘图,总要有数据源吧?DEF 就是告诉 RRDtool 从那个 RRD 中取出指定。

为什么还有一个 CF 字段?因为 RRA 有多种CF 类型,有些 RRA 可能用来保存平均值、有些 RRA 可能用于统计最大值、最小值等等。所以你必须同时指定使用什么 CF 类型的 RRA的数据。

至于 :start 和 :end 、:reduce 则用得比较少,最常用的就是 :step 了,它可以让你控制 RRDtool 从那个 RRA 中取数据。


(2).VDEF 是 Variable Definition (变量定义)的意思。定义什么呢?记得 MRTG 在图表的下面有一个称之为 Legend 的部分吗?那里显示了1个或者2个 DS (MRTG 没有 DS 一说,这里是借用 RRDtool 的)的 “最大值”、“平均值”、“当前值”。


RRDtool 中用 VDEF 来定义。这个变量专门存放某个 DS 某种类型的值,例如 eth0_in 的最大值、eht0_out 的当前值等。当你需要象MRTG 一样输出数字报表(Legend) 时,就可以在 GPRINT 子句(sub clause)中调用它。同样它也需要用一个变量来存放数值。要注意的是,旧版 的 RRDtool 中是用另外一种格式来达到相同的目的。新版的 RRDtool 则推荐使用VDEF语句。但在使用过程中,却发现 VDEF 的使用反而造成了困扰。 例如你有5个 DS 要画,每个 DS 你都想输出最大值、最小值、平均值 、当前值。 如果使用 VDEF ,则需要 4 * 5 = 20 个 VDEF 语句,这会造成极大的困扰。具体例子可以看第十一节“数字报表”部分。


(3).CDEF 是 Calculation Define 的意思。使用过MRTG 的都会体会到一点,MRTG 的计算能力实在太差了。例如你有两个 Target ,一个是 eth0_in , 一个是 eth0_out,如果要把它们相加起来,再除以8,得出 bytes 为单位的值,如何计算呢?或者说你只想看 eth0_in 中超过 10Mb/s 的那部分, 其余的不关心,又如何实现呢?因为 MRTG 不能对它从 log 取出来的数据进行修改,只能原原本本的表现,所以很难满足我们的要求。而使用 CDEF , 这一切都可以很容易的实现。CDEF 支持很多数学运算,甚至还支持简单的逻辑运算 if-then-else ,可以解决前面提到的第2个问题:如何只绘制你所关 心的数据。不过这一切都需要熟悉 RPN 的语法.所以我们放到下一节介绍,这一节就介绍把 RRDtool 中的数据以图表的方式显示出来。


(4).其它选项分类

本部分我们按照官方文档的方式,把选项分成几大类,分为 :

  • Time range : 用于控制图表的X轴显示的起始/结束时间,也包括从RRA中提取指定时间的数据。

  • Labels :用于控制 X/Y 轴的说明文字。

  • Size :用于控制图片的大小。

  • Limits :用于控制 Y 轴的上下限。

  • Grid :用于控制 X/Y 轴的刻度如何显示。

  • Miscellaneous :其他选项。例如显示中文、水印效果等等。

  • Report :数字报表

注,需要说明的是,本博文中并不是列出了所有选项的用法,只是列出较为常用的选项,如果想查看所有选项的的用法,可以到官方站点下载文档。其实大部分选项我们都可以使用默认值不需要修改的。下面是常用选项,

1
rrdtool graph filename [option ...] [data definition ...] [data calculation ...] [variable definition ...] [graph element ...] [print element ...]
  • filename 要绘制的图片名称

  • Time range时间范围

  • [-s|--start time] 启始时间[-e|--end time]结束时间 [-S|--step seconds]步长

  • Labels

  • [-t|--title string]图片的标题 [-v|--vertical-label string] Y轴说明

  • Size

  • [-w|--width pixels] 显示区的宽度[-h|--height pixels]显示区的高度 [-j|--only-graph]

  • Limits

  • [-u|--upper-limit value] Y轴正值高度[-l|--lower-limit value]Y轴负值高度 [-r|--rigid]

  • Data and variables

  • DEF:vname=rrdfile:ds-name:CF[:step=step][:start=time][:end=time]

  • CDEF:vname=RPN expression

  • VDEF:vname=RPN expression

rrdtool创建图的案例:


1、创建一个rrdtool文件
[root@node4 ~]# rrdtool create test.rrd --step 5 DS:testds:GAUGE:8:0:U RRA:AVERAGE:0.5:1:17280 RRA:AVERAGE:0.5:10:3456 RRA:AVERAGE:0.5:100:1210

2、查看该rrd文件的详细信息
[root@node4 ~]# rrdtool info test.rrd
filename = "test.rrd"
rrd_version = "0003"
step = 5
last_update = 1489042989
ds[testds].type = "GAUGE"
ds[testds].minimal_heartbeat = 8
ds[testds].min = 0.0000000000e+00
ds[testds].max = NaN
ds[testds].last_ds = "U"
ds[testds].value = 0.0000000000e+00
ds[testds].unknown_sec = 4
rra[0].cf = "AVERAGE"
rra[0].rows = 17280
rra[0].cur_row = 5733
rra[0].pdp_per_row = 1
rra[0].xff = 5.0000000000e-01
rra[0].cdp_prep[0].value = NaN
rra[0].cdp_prep[0].unknown_datapoints = 0
rra[1].cf = "AVERAGE"
rra[1].rows = 3456
rra[1].cur_row = 2505
rra[1].pdp_per_row = 10
rra[1].xff = 5.0000000000e-01
rra[1].cdp_prep[0].value = NaN
rra[1].cdp_prep[0].unknown_datapoints = 7
rra[2].cf = "AVERAGE"
rra[2].rows = 1210
rra[2].cur_row = 89
rra[2].pdp_per_row = 100
rra[2].xff = 5.0000000000e-01
rra[2].cdp_prep[0].value = NaN
rra[2].cdp_prep[0].unknown_datapoints = 97
You have new mail in /var/spool/mail/root

3、使用rrdtool update命令更新tets.rrd文件
[root@node4 ~]# rrdtool update test.rrd N:$RANDOM

4、使用rrdtool fetch取得test.rrd文件的平均值
[root@node4 ~]# rrdtool fetch test.rrd AVERAGE
1489043725: -nan
1489043730: -nan
1489043735: -nan
1489043740: -nan
1489043745: -nan
1489043750: -nan
1489043755: -nan
1489043760: -nan
1489043765: -nan
......

5、写脚本一直不断的取值
vim  test.sh
#!/bin/bash
while true

do

  rrdtool update test.rrd N:$RANDOM
  sleep 5

done

6、执行脚本
[root@node4 ~]# bash -x test.sh
+ true
+ rrdtool update test.rrd N:30688
+ sleep 5
+ true
+ rrdtool update test.rrd N:8863
+ sleep 5
+ true
+ rrdtool update test.rrd N:2732
+ sleep 5
+ true
+ rrdtool update test.rrd N:12843
+ sleep 5
+ true
+ rrdtool update test.rrd N:20395

7、查看rrd数据库生成的值,可以看到已经取到数值


8、使用这些数值出图
绘一张名为a.png的图,每5秒出一次
[root@node4 ~]# rrdtool graph  a.png  --step 5 -s 1489606160  DEF:vartest=/root/test.rrd:testds:AVERAGE LINE1:vartest#FF0000:"testline"


绘一张名为b.png的图,每50秒出一次
[root@node4 ~]# rrdtool graph  b.png  --step 50 -s 1489606160  DEF:vartest=/root/test.rrd:testds:AVERAGE LINE1:vartest#FF0000:"testline"


9、定义一个mysql查询的rrd文件名为mysql.rrd
[root@node4 ~]# rrdtool create mysql.rrd --step 3 DS:myselect:COUNTER:5:0:U RRA:AVERAGE:0.5:1:28800 RRA:AVERAGE:0.5:10:2880 RRA:MAX:0.5:10:2880 RRA:LAST:0.5:10:2880
You have new mail in /var/spool/mail/root

10、写个脚本不断查询插入的数据

vim  select.sh

#!/bin/bash

while true

do

SELECT=`mysql --batch -e "SHOW GLOBAL STATUS LIKE 'com_select' "| awk '/Com_select/ {print $2}'`

rrdtool update mysql.rrd N:$SELECT

sleep 3

done

11、不断的执行该脚本
[root@node4 ~]# bash -x select.sh
[root@node4 ~]# bash -x select.sh
+ true
++ awk '/Com_select/ {print $2}'
++ mysql --batch -e 'SHOW GLOBAL STATUS LIKE '\''com_select'\'' '
+ SELECT=20
+ rrdtool update mysql.rrd N:20
+ sleep 3
+ true

12、mysql创建个数据库,并创建一个tb1的表
mysql> CREATE DATABASE testdb;
Query OK, 1 row affected (0.06 sec)

mysql> use testdb;
Database changed

mysql> create table tb1(ID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, NAME CHAR(50) NOT NULL);
Query OK, 0 rows affected (0.04 sec)

13、写个脚本不断的往表里插入数据
vim insert.sh

#!/bin/bash
#

for I in {1...200000}; do

     mysql -e "INSERT INTO testdb.tb1(NAME) VALUES('stu$I')"
     mysql -e "SELECT * FROM testdb.tb1" &> /dev/null

done

14、执行insert.sh的脚本
bash -x insert.sh


15、查看rrd文件里更新的数据,查看每5秒的平均值
rrdtool fetch -r 5 mysql.rrd AVERAGE

1489611681: -nan
1489611684: -nan
1489611687: -nan
1489611690: -nan
1489611693: -nan
1489611696: -nan
1489611699: 3.2276013371e-01
1489611702: 3.2439909247e-01
1489611705: 3.2509059766e-01
1489611708: 3.2534865880e-01
1489611711: 3.2310571813e-01
1489611714: 3.2552196069e-01
1489611717: 3.2617244821e-01
1489611720: 3.2047727718e-01
1489611723: 3.2249823629e-01
1489611726: 3.2921477857e-01


16、查看rrd文件里更新的数据,查看每30秒的平均值
rrdtool fetch -r 30 mysql.rrd AVERAGE

1489611540: -nan
1489611570: -nan
1489611600: -nan
1489611630: -nan
1489611660: -nan
1489611690: -nan
1489611720: 3.2410948586e-01
1489611750: 3.2735124698e-01
1489611780: 3.2608123676e-01
1489611810: 3.2611858157e-01
1489611840: 3.2885016057e-01
1489611870: 3.2918310390e-01
1489611900: 3.2986936994e-01
1489611930: 3.2989331809e-01
1489611960: 3.2930017799e-01
1489611990: 3.2933485114e-01
1489612020: 3.2950317267e-01
1489612050: 3.2875656139e-01

17、使用获取的值生成图像,mysql每3秒的查询次数
[root@node4 ~]# rrdtool graph mysql.png -s 1489611630 -t "mysql select" -v "selects/3" DEF:select3=mysql.rrd:myselect:AVERAGE:step=3 LINE1:select3#FF0000:"SELECT"
497x174


18、使用获取的值生成图像,mysql每30秒的查询次数
[root@node4 ~]# rrdtool graph mysql1.png -s 1489611630 -t "mysql select" -v "selects/3" DEF:select30=mysql.rrd:myselect:AVERAGE:step=30 LINE1:select30#FF0000:"SELECT"
497x174


19、打印出底边的字符,并显示最大的值
[root@node4 ~]# rrdtool graph mysql1.png -s 1489611630 -t "mysql select" -v "selects/3" DEF:select30=mysql.rrd:myselect:AVERAGE:step=30 DEF:max30=mysql.rrd:myselect:MAX:step=30 LINE1:select30#FF0000:"SELECT" GPRINT:max30:MAX:"MAXIMUM\: %6.2lf"
497x174


20、打印出底边的字符,并显示当前的值
[root@node4 ~]# rrdtool graph mysql1.png -s 1489611630 -t "mysql select" -v "selects/3" DEF:select30=mysql.rrd:myselect:AVERAGE:step=30 DEF:max30=mysql.rrd:myselect:MAX:step=30 DEF:last30=mysql.rrd:myselect:LAST:step=30  LINE1:select30#FF0000:"SELECT" GPRINT:last30:LAST:"CURRENT\: %10.2lf" GPRINT:max30:MAX:"MAXIMUM\: %6.2lf"





阅读(1473) | 评论(0) | 转发(0) |
0

上一篇:Mysql insert

下一篇:Puppet 使用详解

给主人留下些什么吧!~~