利用脚本扩展snmp收集信息
来源:互联网 发布:淘宝优惠券发放软件 编辑:程序博客网 时间:2024/06/09 13:55
- snmpd.conf简单配置
- 通过脚本方式扩展agent采集自身所需要的信息
- 一个基于snmp4j的snmp manager实现
有关snmp的介绍不想多说,它本身只是一个协议,在各操作系统平台下都有自己的实现。由于集群都是Linux系统,所以选择了最流行的net-snmp,各个Linux版本的软件库中应该都会包含(其实windows下面也有)。软件本身也可分为agent(snmpd包)和manager(snmp包)两部分。顾名思义,snmpd作为deamon,应该部署到被监控的节点上;而manager则包含了一系列snmpget、snmpset、snmpwalk等工具,应该被安装在监控服务器上。由于我们会用snmp4j来进行信息收集和一些配置工作(它本身就能提供snmpget、snmpset等功能),因此从理论上来讲,snmp这个包可有可无,但为了方便调试,一般还是会装上。
在安装完snmpd之后,首要任务是修改/etc/snmp/snmpd.conf配置。默认的配置文件会给出很多的注释和参考示例,很清晰。总结来说需要修改或添加以下项:
agentAddress udp:161,udp6:[::1]:161 ####### 为了能在非本地访问,监听所有161端口view all❘-included .1 ####### 添加一个名为all的可以访问.1入口下所有MIB库的组rwcommunity test default -V all ####### 添加一个对于组all具有读写权限的用户名testextend-sh disk_info_sda1 /bin/bash /tmp/script/disk_info.sh sda1 ####### 扩展一个名为disk_info_sda1的项,执行所给地址的脚本,并以sda1为参数,结果为脚本的输出值注意修改完后要重启一下snmpd服务。snmp协议的3个版本,只有v3才提供了安全方面的功能,也可以通过这个文件配置,这里我们先略去不谈。
snmp以MIB库的形式来管理数据。就像是一棵树,其每个叶子节点所对应的OID都可以用来访问某个特定的数据项。可以利用snmpget命令来获取某个OID对应的值,也可以用snmpwalk来遍历以给定节点为根的子树,输出其包含的所有数据项。snmp本身为我们提供了很多可以获取的有用的数据,可以通过http://www.oidview.com/mibs/detail.html这个网站进行查询,但有时候,这些数据格式或内容可能与我们想要的不一致,这时候就要用到agent扩展。net-snmp本身提供了多种扩展方式,我们仅用到了最简单的脚本方式(上述已经配置过),新添加的扩展都会被添加到NET-SNMP-EXTEND-MIB(1.3.6.1.4.1.8072.1.3.2)这个入口之下。我们通过遍历命令,可以得到如下结果(假设只有一个disk_info_sda1扩展项):
snmpwalk -v 2c -c test localhost 1.3.6.1.4.1.8072.1.3.2NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 1NET-SNMP-EXTEND-MIB::nsExtendCommand."disk_info_sda1" = STRING: /bin/bashNET-SNMP-EXTEND-MIB::nsExtendArgs."disk_info_sda1" = STRING: /tmp/script/disk_info.sh sda1NET-SNMP-EXTEND-MIB::nsExtendInput."disk_info_sda1" = STRING: NET-SNMP-EXTEND-MIB::nsExtendCacheTime."disk_info_sda1" = INTEGER: 5NET-SNMP-EXTEND-MIB::nsExtendExecType."disk_info_sda1" = INTEGER: shell(2)NET-SNMP-EXTEND-MIB::nsExtendRunType."disk_info_sda1" = INTEGER: run-on-read(1)NET-SNMP-EXTEND-MIB::nsExtendStorage."disk_info_sda1" = INTEGER: permanent(4)NET-SNMP-EXTEND-MIB::nsExtendStatus."disk_info_sda1" = INTEGER: active(1)NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."disk_info_sda1" = STRING: 32,169NET-SNMP-EXTEND-MIB::nsExtendOutputFull."disk_info_sda1" = STRING: 32,169NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."disk_info_sda1" = INTEGER: 1NET-SNMP-EXTEND-MIB::nsExtendResult."disk_info_sda1" = INTEGER: 0NET-SNMP-EXTEND-MIB::nsExtendOutLine."disk_info_sda1".1 = STRING: 32,169
由于本机在/usr/share/mibs/netsnmp下有MIB定义文件NET-SNMP-EXTEND-MIB的存在,walk工具会自动将那一连串难记的数字转换为可读的名称。当然,也可以通过-O n参数显示原始的数字:
snmpwalk -v 2c -c test -O n localhost 1.3.6.1.4.1.8072.1.3.2.1.3.6.1.4.1.8072.1.3.2.1.0 = INTEGER: 1.1.3.6.1.4.1.8072.1.3.2.2.1.2.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = STRING: /bin/bash.1.3.6.1.4.1.8072.1.3.2.2.1.3.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = STRING: /tmp/script/disk_info.sh sda1.1.3.6.1.4.1.8072.1.3.2.2.1.4.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = STRING: .1.3.6.1.4.1.8072.1.3.2.2.1.5.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = INTEGER: 5.1.3.6.1.4.1.8072.1.3.2.2.1.6.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = INTEGER: shell(2).1.3.6.1.4.1.8072.1.3.2.2.1.7.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = INTEGER: run-on-read(1).1.3.6.1.4.1.8072.1.3.2.2.1.20.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = INTEGER: permanent(4).1.3.6.1.4.1.8072.1.3.2.2.1.21.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = INTEGER: active(1).1.3.6.1.4.1.8072.1.3.2.3.1.1.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = STRING: 32,169.1.3.6.1.4.1.8072.1.3.2.3.1.2.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = STRING: 32,169.1.3.6.1.4.1.8072.1.3.2.3.1.3.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = INTEGER: 1.1.3.6.1.4.1.8072.1.3.2.3.1.4.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 = INTEGER: 0.1.3.6.1.4.1.8072.1.3.2.4.1.2.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49.1 = STRING: 32,169
名称和数字有些类似于域名和IP地址的关系。这里顺便给出disk_info.sh的脚本如下:
#!/bin/bashif [ $# -lt 1 ]; then echo "Usage: disk_info [disk name]"; exit 1;fidiskName=$1disk_info=`df -m | grep $diskName' '|awk '{print $1" "$2" "$3" "$4" "$5" "$6" "}'`used=`echo $disk_info|awk '{print $3}'`available=`echo $disk_info|awk '{print $4}'`if [ -z "$used" ]then used='0'fiif [ -z "$available" ]then available='0'fiecho $used","$available
很简单,它的作用就是输出给定磁盘的已用空间和剩余空间,以MB为单位,中间用逗号隔开。上文中NET-SNMP-EXTEND-MIB::nsExtendOutputFull."disk_info_sda1" = STRING: 32,169 就是示例输出。换句话说,我们如果想随时获取节点sda1磁盘的空间情况,只需要执行snmpget -v 2c -c test localhost 1.3.6.1.4.1.8072.1.3.2.3.1.1.14.100.105.115.107.95.105.110.102.111.95.115.100.97.49 即可。
由于开发语言选用的Java,所以找到了一个名为snmp4j(http://www.snmp4j.org/)的snmp的另一个实现,它提供了很多API可供我们使用。与net-snmp类似,snmp4j也有agent和manager一说,这里我们将只用到它的manager。给出一个对snmp4j的API进行封装后的SNMPManager实现如下:
import java.io.IOException;import java.util.LinkedList;import java.util.List;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.snmp4j.CommunityTarget;import org.snmp4j.PDU;import org.snmp4j.Snmp;import org.snmp4j.Target;import org.snmp4j.TransportMapping;import org.snmp4j.event.ResponseEvent;import org.snmp4j.mp.SnmpConstants;import org.snmp4j.smi.Address;import org.snmp4j.smi.GenericAddress;import org.snmp4j.smi.Integer32;import org.snmp4j.smi.OID;import org.snmp4j.smi.OctetString;import org.snmp4j.smi.UdpAddress;import org.snmp4j.smi.Variable;import org.snmp4j.smi.VariableBinding;import org.snmp4j.transport.DefaultUdpTransportMapping;import org.snmp4j.util.DefaultPDUFactory;import org.snmp4j.util.TreeEvent;import org.snmp4j.util.TreeUtils;import util.OIDUtil;/** * A snmp4j based SNMP Manager * * @author grandland.xccui * */public class SNMPManager {private static final Logger LOG = LoggerFactory.getLogger(SNMPManager.class);private Snmp snmp;private CommunityTarget target;private Address address;private String community;/** * * @param addrStr * the agent address * @param port * the agent port * @param community * the community name for access */public SNMPManager(String addrStr, int port, String community) {this.community = community;this.address = GenericAddress.parse(addrStr + "/" + port);this.target = null;}/** * Start the SNMP manager * * @throws IOException */public void start() throws IOException {TransportMapping<UdpAddress> transportMapping = new DefaultUdpTransportMapping();snmp = new Snmp(transportMapping);snmp.listen();}/** * Walk MIB tree with the given oid as the root * * @param oid * @return * @throws IOException */public List<VariableBinding> walkAsList(String oid) throws IOException {TreeUtils treeUtils = new TreeUtils(snmp, new DefaultPDUFactory());List<TreeEvent> events = treeUtils.getSubtree(getTarget(), new OID(oid));LinkedList<VariableBinding> resultList = new LinkedList<VariableBinding>();for (TreeEvent event : events) {if (event != null) {if (event.isError()) {LOG.warn("oid [" + oid + "] " + event.getErrorMessage());}VariableBinding[] varBindings = event.getVariableBindings();if (varBindings != null && varBindings.length > 0) {for (VariableBinding vb : varBindings) {resultList.add(vb);}}}}return resultList;}/** * Get values for each oid in the given array * * @param oids * @return * @throws IOException */public List<VariableBinding> getAsList(String... oids) throws IOException {List<VariableBinding> resultList = new LinkedList<VariableBinding>();PDU pdu = new PDU();pdu.setType(PDU.GET);for (String oid : oids) {pdu.add(new VariableBinding(new OID(oid)));}ResponseEvent event = snmp.get(pdu, getTarget());if (null != event) {PDU response = event.getResponse();if (null != response) {int length = response.size();for (int i = 0; i < length; i++) {resultList.add(response.get(i));}}LOG.debug(resultList.toString());}return resultList;}/** * Set integer value for the given oid * * @param oid * @param value * @return */public boolean setInteger(String oid, int value) {try {return set(oid, new Integer32(value));} catch (IOException e) {e.printStackTrace();return false;}}/** * Set string value for the given oid * * @param oid * @param value * @return */public boolean setString(String oid, String value) {try {return set(oid, new OctetString(value));} catch (IOException e) {e.printStackTrace();return false;}}/** * Close the snmp manager * * @throws IOException */public void close() throws IOException {snmp.close();}private boolean set(String oid, Variable variable) throws IOException {VariableBinding binding = new VariableBinding(new OID(oid), variable);PDU pdu = new PDU();pdu.setType(PDU.SET);pdu.add(binding);ResponseEvent event = snmp.set(pdu, getTarget());if (event.getResponse().getErrorStatus() != PDU.noError) {LOG.warn("oid [" + oid + "] variable [" + variable.toString()+ "] " + event.getResponse().getErrorStatusText());return false;}return true;}private synchronized Target getTarget() {if (null != target) {return target;}target = new CommunityTarget();target.setCommunity(new OctetString(community));target.setAddress(address);target.setRetries(2);target.setTimeout(1500);target.setVersion(SnmpConstants.version2c);return target;}}
其中还用到了一个OIDUtil工具:
public class OIDUtil {public static final String NET_SNMP_EXTEND_BASE = "1.3.6.1.4.1.8072.1.3.2.";public static final String NET_SNMP_EXTEND_nsExtendCacheTime_BASE = NET_SNMP_EXTEND_BASE+ "2.1.5.";public static final String NET_SNMP_EXTEND_nsExtendOutputFull_BASE = NET_SNMP_EXTEND_BASE+ "3.1.2.";public static String toOIDSeq(String str) {StringBuilder sb = new StringBuilder();int length = str.length();for (int i = 0; i < length; i++) {sb.append("." + (int) str.charAt(i));}return sb.toString();}public static String genCacheTimeOID(String name) {return NET_SNMP_EXTEND_nsExtendCacheTime_BASE+ name.length()+ toOIDSeq(name);}public static String genOutputFullOID(String name) {return NET_SNMP_EXTEND_nsExtendOutputFull_BASE + name.length()+ toOIDSeq(name);}}
这个工具类的作用是根据给定的扩展名称,也就是上文中的disk_info_sda1,来生成其对应的缓存时间项和输出结果项的OID,免去了指定那一长串数字的麻烦(OID的生成方式是一段base+名称长度+名称每一位对应的ASCII值)。当然,这里没有进行再深入的研究,snmp4j应该也能支持直接通过MIB表内的名称进行访问。
为什么还需要缓存时间这一项呢?实际中发现,为了提高效率,net-snmp的agent不会每次都去执行脚本,而是会将上次结果缓存某个时间,默认是5秒。在这段时间之内无论你访问多少次,结果都是一样的。一些对实时性要求比较高的信息,如CPU使用率等,如果访问间隔小于缓存时间,得到的结果就会很难看。所以每次在开始定期收集数据之前,需要利用SNMPManager里的setInteger方法,来设置一个小于采集间隔的缓存时间。
- 利用脚本扩展snmp收集信息
- 20170313ZABBIX SNMP客户端收集DISK信息脚本
- 收集扩展统计信息
- windows oid 利用SNMP获得主机信息
- windows oid 利用SNMP获得主机信息
- Monkey信息自动收集脚本
- 利用statspack收集数据库信息
- 利用metasploit进行信息收集
- oradebug.sh os信息收集脚本
- Android APP Monkey信息自动收集脚本
- vretica自动收集统计信息脚本
- 11g统计信息收集脚本
- 利用dbms_stats收集统计信息(待续)
- 利用phpize脚本安装PHP扩展模块
- SNMP代理扩展
- PySNMP扩展snmp-trap
- Net-snmp agent扩展
- 自定义SNMP Agent扩展
- oracle job使用详解及job不运行的检查方法
- popShow弹出层的使用(二)
- 阿里云服务器初次使用
- 如何在Linux下统计高速网络中的流量
- VLOOKUP制作EXCEL动态图
- 利用脚本扩展snmp收集信息
- csdn 以【源代码】的格式显示所贴的代码
- 可搜索、可多选的下拉列表控件使用
- Android设计模式系列(1)--SDK源码之组合模式
- Gesture - Rotation旋转
- TinyXml快速入门(增删节点)
- 如何在service中弹出dialog
- Google研制智能隐形眼镜 帮助病人监测血糖指标
- 数字之和排序