Java使用snmp协议采集服务器信息
Java使用snmp协议采集服务器信息
一.snmp简介
SNMP是专门设计用于在 IP 网络管理网络节点(服务器、工作站、路由器、交换机及Hubs等)的一种标准协议,它是一种应用层协议。 SNMP 使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长。通过SNMP接收随机消息(及事件报告)网络管理系统获知网络出现问题。
SNMP的前身是简单网关监控协议(SGMP),用来对通信线路进行管理。随后,人们对SGMP进行了很大的修改,特别是加入了符合Internet定义的SMI和MIB,改进后的协议就是著名的SNMP。基于TCP/IP的SNMP网络管理框架是工业上的现行标准,由3个主要部分组成,分别是管理信息结构SMI(Structure ofManagement Information)、管理信息库MIB和管理协议SNMP。
- SMI定义了SNMP框架所用信息的组织和标识,为MIB定义管理对象及使用管理对象提供模板。
- MIB定义了可以通过SNMP进行访问的管理对象的集合。
- SNMP协议是应用层协议,定义了网络管理者如何对代理进程的MIB对象进行读写操作。
SNMP中的MIB是一种树状数据库,MIB管理的对象,就是树的端节点,每个节点都有唯一位置和唯一名字。IETF规定管理信息库对象识别符(OID,Object Identifier)唯一指定,其命名规则就是父节点的名字作为子节点名字的前缀。
二、开发集成
<!-- https://mvnrepository.com/artifact/org.snmp4j/snmp4j --> <dependency> <groupId>org.snmp4j</groupId> <artifactId>snmp4j</artifactId> <version>2.7.0</version> </dependency>
https://mvnrepository.com/artifact/org.snmp4j/snmp4j
目前最新版本3.7.7,目前以2.7.0版本为例。
三、基础OID
import java.math.BigDecimal; /** * snmp协议工具类配置文件 */ public class SnmpConfig { private SnmpConfig(){} /** * get cpu描述信息 */ public static final String SNMPGET_CPUDESC=".1.3.6.1.2.1.1.1.0.255.1"; /** * walk 网络接口描述 */ public static final String SNMPWALK_IFDESCR=".1.3.6.1.2.1.2.2.1.2"; /** * walk 接口物理地址 */ public static final String SNMPWALK_IFPHYSADDRESS=".1.3.6.1.2.1.2.2.1.6"; /** * get IO负载 */ public static final String SNMPGET_IOLOAD=".1.3.6.1.2.1.1.1.0.255.0"; /** * 硬盘大小 */ public static final String SNMPGET_DSKTOTAL=".1.3.6.1.4.1.2021.9.1.6"; /** * walk cpu 负载 */ public static final String SNMPWALK_HRPROCESSLOAD=".1.3.6.1.2.1.25.3.3.1.2"; /** * walk cpu 空闲率 */ public static final String SNMPWALK_SSCPUIDLE=".1.3.6.1.4.1.2021.11.11.0"; /** * walk 存储设备描述 */ public static final String SNMPWALK_HRSTORAGEDESCR=".1.3.6.1.2.1.25.2.3.1.3"; /** * walk 存储设备描述 */ public static final String SNMPWALK_AHU=".1.3.6.1.2.1.25.2.3.1.4"; /** * walk 存储设备描述 */ public static final String SNMPWALK_AUR=".1.3.6.1.2.1.25.2.3.1.5"; /** *walk 存储设备使用大小 * 内存使用多少,跟总容量相除就是占用率 */ public static final String SNMPWALK_HRSTORAGEUSED=".1.3.6.1.2.1.25.2.3.1.6"; /** *walk 内存占用 * 各个进程占用的内存 */ public static final String SNMPWALK_MEMORY_WIN=".1.3.6.1.2.1.25.5.1.1.2"; /** *walk 存储设备使用率 * */ public static final String SNMPWALK_DSKPERCENT=".1.3.6.1.4.1.2021.9.1.9"; /** * get 获取内存大小 */ public static final String SNMPGET_HRMEMORYSIZE=".1.3.6.1.2.1.25.2.2.0"; /** * 获取机器名 */ public static final String SNMPWALK_SYSNAME=".1.3.6.1.2.1.1.5"; /** * 性能参数ID-cpu使用率 */ public static final Integer PERFORMANCE_PARAM_CPUUSAGE=1; /** * 性能参数ID-内存使用率 */ public static final Integer PERFORMANCE_PARAM_MEMORYUSAGE=2; /** * 性能参数ID-io带宽占用率 */ public static final Integer PERFORMANCE_PARAM_IOUSAGE=3; /** * decimal 类型1024,用于除法计算 */ public static final BigDecimal DEVIDE_NUM=new BigDecimal("1024"); /** * get方式获取内存大小 */ public static final String GET_MEMORY="1.3.6.1.2.1.25.2.2.0"; /** * 获取系统描述 */ public static final String SYS_DSC="1.3.6.1.2.1.1.1.0"; /** * 获取网络接口数量 */ public static final String IF_NUM="1.3.6.1.2.1.2.1.0"; /** * 获取cpu核数 */ public static final String CPU_NUM="1.3.6.1.2.1.25.3.3.1.2"; }
四、snmp信息采集工具类
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.snmp4j.CommunityTarget; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.event.ResponseEvent; import org.snmp4j.mp.SnmpConstants; import org.snmp4j.smi.OID; import org.snmp4j.smi.OctetString; import org.snmp4j.smi.UdpAddress; import org.snmp4j.smi.VariableBinding; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.snmp4j.util.DefaultPDUFactory; import org.snmp4j.util.TableEvent; import org.snmp4j.util.TableUtils; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.List; /** * snmp协议工具类 * 获取服务器cpu,内存,及硬盘占用 */ public class SnmpUtil { private static Logger logger = LogManager.getLogger(SnmpUtil.class); private static Snmp snmp = null; private CommunityTarget target; @SuppressWarnings("squid:S3010") public SnmpUtil(String intranetDeviceIp, Integer snmpPort) throws IOException { if (snmp == null) { snmp = new Snmp(new DefaultUdpTransportMapping()); snmp.listen(); } //初始化CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString("public")); target.setVersion(SnmpConstants.version2c); target.setAddress(new UdpAddress(intranetDeviceIp + "/" + snmpPort)); target.setTimeout(1000); target.setRetries(1); } private ResponseEvent snmpGet(String oid) { PDU pdu = new PDU(); pdu.addOID(new VariableBinding(new OID(oid))); ResponseEvent re=null; try { re = snmp.get(pdu, target); }catch (Exception e){ logger.info("snmpGet 异常"+e.getMessage()); } return re; } private List<TableEvent> snmpWalk(String oid) { TableUtils utils = new TableUtils(snmp, new DefaultPDUFactory(PDU.GETBULK)); OID[] columnOid = new OID[]{new OID(oid)}; return utils.getTable(target, columnOid, null, null); } /** * 获取cpu负载 * @return */ public BigDecimal getCpuUsage() { List<TableEvent> list = snmpWalk(SnmpConfig.SNMPWALK_HRPROCESSLOAD); BigDecimal usage = new BigDecimal("0"); for (TableEvent tableEvent : list) { try { String s=tableEvent.toString().split("=")[3].split("]")[0].trim(); if (!"-4,exception".equals(s)){ usage=usage.add(new BigDecimal(tableEvent.toString().split("=")[3].split("]")[0].trim())); }else { return new BigDecimal("-1"); } } catch (Exception e) { logger.info("获取cpu负载失败"+e.getMessage()); return new BigDecimal("-1"); } } usage = usage.divide(new BigDecimal(list.size()),2,BigDecimal.ROUND_HALF_UP); return usage; } /** * 获取cpu使用率 * @return */ public BigDecimal getCpu() { BigDecimal totalSize; ResponseEvent responseEvent = snmpGet(SnmpConfig.SNMPWALK_SSCPUIDLE); if(responseEvent!=null&&responseEvent.getResponse()!=null){ totalSize=new BigDecimal(responseEvent.getResponse().toString().split("=")[4].split("]")[0].trim()); }else { return new BigDecimal("-1"); } return new BigDecimal("100").subtract(totalSize); } /** * 获取磁盘占用率 * @return */ public BigDecimal getDiskUsageForWindows() { BigDecimal multiply=new BigDecimal("-1"); try { BigDecimal diskSize = getDiskSize(); BigDecimal diskUsed = getDiskUsed(); if (BigDecimal.ZERO.compareTo(diskSize)<0&&BigDecimal.ZERO.compareTo(diskUsed)<0){ multiply = getDiskUsed().divide(getDiskSize(), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)); } }catch (Exception e){ logger.info("获取windows磁盘占用异常"+e.getMessage()); } return multiply; } /** * 获取磁盘占用率 * @return */ public BigDecimal getDiskUsage() { BigDecimal totalSize=null; //org.snmp4j.util.TableEvent[index=null,vbs=null,status=-1,exception=null,report=null] List<TableEvent> tableEvents = snmpWalk(SnmpConfig.SNMPWALK_DSKPERCENT); if(tableEvents.isEmpty()){ totalSize = getDiskUsageForWindows(); return totalSize; } for(int i=0;i<tableEvents.size();i++){ if ("-1,exception".equals(tableEvents.get(i).toString().split("=")[3].split("]")[0].trim())){ return new BigDecimal("-1"); } String s=tableEvents.get(i).toString().split("=")[3].split("]")[0].trim(); if (!"-4,exception".equals(s)){ totalSize= new BigDecimal(tableEvents.get(i).toString().split("=")[3].split("]")[0].trim()); }else { return new BigDecimal("-1"); } } return totalSize; } /** * 获取内存使用率 * @return */ public BigDecimal getMemoryUsage(){ BigDecimal usage; BigDecimal totalSize; try { ResponseEvent event = snmpGet(SnmpConfig.SNMPGET_HRMEMORYSIZE); if (event != null && event.getResponse() != null) { totalSize = new BigDecimal(event.getResponse().toString().split("=")[4].split("]")[0].trim()); usage = getMemoryUsed(); return usage.multiply(new BigDecimal("100")).divide(totalSize, 0, BigDecimal.ROUND_HALF_UP); } else { return new BigDecimal("-1"); } }catch (Exception e){ logger.info("获取内存使用率失败"+e.getMessage()); return new BigDecimal("-1"); } } /** * 获取内存已使用 * @return */ public BigDecimal getMemoryUsed(){ List<TableEvent> list=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEDESCR); int index=0; BigDecimal usedMemory=new BigDecimal("0"); for(int i=0;i<list.size();i++){ String trim = list.get(i).toString().split("=")[3].split("]")[0].trim(); if(trim.contains("Physical memory")){ //linux系统 index=i; List<TableEvent> usedList=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED); usedMemory= new BigDecimal(usedList.get(index).toString().split("=")[3].split("]")[0].trim()); }else if (trim.contains("Physical Memory")){ //windows系统 List<TableEvent> list1=snmpWalk(SnmpConfig.SNMPWALK_MEMORY_WIN); BigDecimal re=new BigDecimal("0"); for (int j=0;j<list1.size();j++){ String trim1 = list1.get(j).toString().split("=")[3].split("]")[0].trim(); BigDecimal b = new BigDecimal(trim1); re=re.add(b); } return re; }else if(trim.contains("Memory buffers")){ //linux系统 index=i; List<TableEvent> usedList=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED); usedMemory= usedMemory.subtract(new BigDecimal(usedList.get(index).toString().split("=")[3].split("]")[0].trim())); }else if(trim.contains("Cached memory")){ //linux系统 index=i; List<TableEvent> usedList=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED); usedMemory= usedMemory.subtract(new BigDecimal(usedList.get(index).toString().split("=")[3].split("]")[0].trim())); } } return usedMemory; } /** * 获取磁盘 * @return */ public BigDecimal getDiskSize(){ List<TableEvent> list=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEDESCR); BigDecimal diskSize=new BigDecimal(-1); if (!list.isEmpty()){ diskSize=new BigDecimal("0"); List<TableEvent> usedList1=snmpWalk(SnmpConfig.SNMPWALK_AHU); List<TableEvent> usedList2=snmpWalk(SnmpConfig.SNMPWALK_AUR); for(int i=0;i<list.size();i++){ boolean re=list.get(i).toString().split("=")[3].split("]")[0].trim().contains(":")||list.get(i).toString().split("=")[3].split("]")[0].trim().contains("/"); if(re){ diskSize=diskSize.add(new BigDecimal(usedList1.get(i).toString().split("=")[3].split("]")[0].trim()).multiply(new BigDecimal(usedList2.get(i).toString().split("=")[3].split("]")[0].trim())).divide(new BigDecimal("1073741824"),2,BigDecimal.ROUND_HALF_UP)); } } } return diskSize; } /** * 获取磁盘已使用 * @return */ public BigDecimal getDiskUsed(){ List<TableEvent> list=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEDESCR); BigDecimal diskSize=new BigDecimal(-1); if (!list.isEmpty()){ diskSize=new BigDecimal("0"); List<TableEvent> usedList1=snmpWalk(SnmpConfig.SNMPWALK_AHU); List<TableEvent> usedList2=snmpWalk(SnmpConfig.SNMPWALK_HRSTORAGEUSED); for(int i=0;i<list.size();i++){ boolean re=list.get(i).toString().split("=")[3].split("]")[0].trim().contains(":")||list.get(i).toString().split("=")[3].split("]")[0].trim().contains("/"); if(re){ diskSize=diskSize.add(new BigDecimal(usedList1.get(i).toString().split("=")[3].split("]")[0].trim()).multiply(new BigDecimal(usedList2.get(i).toString().split("=")[3].split("]")[0].trim())).divide(new BigDecimal("1073741824"),2,BigDecimal.ROUND_HALF_UP)); } } } return diskSize; } /** * 获取IO负载 * @return */ public Float getIOUsage(){ ResponseEvent event=snmpGet(SnmpConfig.SNMPGET_IOLOAD); if(event!=null&&event.getResponse()!=null){ float usage=Float.parseFloat(event.getResponse().toString().split("=")[4].split("]")[0].trim()); if(usage>1){ return usage; }else{ return usage*100; } } return null; } /** * 获取性某性能参数数据 * @param parameterId * @return */ public Object getData(Integer parameterId) { Object data=null; try{ if(parameterId.equals(SnmpConfig.PERFORMANCE_PARAM_CPUUSAGE)){ data=getCpuUsage(); }else if(parameterId.equals(SnmpConfig.PERFORMANCE_PARAM_MEMORYUSAGE)){ data=getMemoryUsage(); }else if(parameterId.equals(SnmpConfig.PERFORMANCE_PARAM_IOUSAGE)){ data=getIOUsage(); } }catch(Exception e){ logger.info("获取性能参数异常"+e.getMessage()); } return data; } /** * 获取设备物理地址 * @return */ public String getMacAddress(){ try { List<TableEvent> list = snmpWalk(SnmpConfig.SNMPWALK_IFDESCR); int index = 0; for (int i = 0; i < list.size(); i++) { if (list.get(i).toString().split("=")[3].split("]")[0].trim().contains("eth")) { index = i; } } List<TableEvent> ifAddressList = snmpWalk(SnmpConfig.SNMPWALK_IFPHYSADDRESS); return ifAddressList.get(index).toString().split("=")[3].split("]")[0].trim(); }catch (Exception e){ logger.info("获取物理地址失败"+e.getMessage()); return "failure"; } } /** * 获取设备内存大小 单位为GB * @return */ public String getMemoryDesc() { ResponseEvent event =snmpGet(SnmpConfig.SNMPGET_HRMEMORYSIZE); Long bytes =Long.parseLong(event==null?"0":event.getResponse().toString().split("=")[4].split("]")[0].trim()); float gb =bytes/1024.0f/1024.0f; DecimalFormat decimalFormat =new DecimalFormat(".00"); return decimalFormat.format(gb)+"GB"; } /** * @throws IOException * 获取cpu描述信息 * @return */ public String getCpuDesc() throws IOException { ResponseEvent event=snmpGet(SnmpConfig.SNMPGET_CPUDESC); return event==null? "":event.getResponse().toString().split("=")[4].split("]")[0].trim().split(":")[1].trim(); } /** * 获取存储设备大小 (空盘空间不足百分百) * @param deviceCode * @return */ public BigDecimal getDiskSize(String deviceCode){ List<TableEvent> list = snmpWalk(SnmpConfig.SNMPGET_DSKTOTAL); BigDecimal diskSize=new BigDecimal(-1); if (list!=null){ try { for (TableEvent tableEvent:list){ diskSize=new BigDecimal(tableEvent.toString().split("=")[3].split("]")[0].trim()).divide(SnmpConfig.DEVIDE_NUM).divide(SnmpConfig.DEVIDE_NUM,2,RoundingMode.HALF_UP); } }catch (Exception e){ logger.info("获取磁盘大小失败"+e.getMessage()); } } if (BigDecimal.ZERO.compareTo(diskSize)>0){ diskSize = getDiskSize(); } return diskSize; } /** * 获取磁盘描述 * @param deviceCode * @return * @throws IOException */ public BigDecimal getDiskDesc(String deviceCode) { return getDiskSize(deviceCode).divide(SnmpConfig.DEVIDE_NUM,2,RoundingMode.HALF_UP).divide(SnmpConfig.DEVIDE_NUM,2,RoundingMode.HALF_UP); } /** * snmp协议检测 */ public boolean snmpCheck() { ResponseEvent re=snmpGet(".1.3.6.1.4.1.2021.255.1"); return re == null || re.getResponse() != null; } /** * 获取机器名 * @return */ public String getSysName(){ String name=null; try{ List<TableEvent> list = snmpWalk(SnmpConfig.SNMPWALK_SYSNAME); if (list!=null){ for (TableEvent tableEvent:list){ name=(tableEvent.toString().split("=")[3].split("]")[0].trim()); } } }catch (Exception e){ logger.info("获取机器名失败"+e.getMessage()); } return name; } /** * 获取内存总大小(实际值) * @return */ public BigDecimal getMemoryTotalSize(){ try { ResponseEvent event = snmpGet(SnmpConfig.GET_MEMORY); if (event!=null&&event.getResponse()!=null){ String trim = event.getResponse().toString().split("=")[4].split("]")[0].trim(); return new BigDecimal(trim).divide(SnmpConfig.DEVIDE_NUM,2, RoundingMode.HALF_UP).divide(SnmpConfig.DEVIDE_NUM,2, RoundingMode.HALF_UP); }else { throw new RuntimeException("获取内存信息失败"); } } catch (Exception e) { logger.info("获取内存总大小失败"+e.getMessage()); } return new BigDecimal("-1"); } /** * 获取系统描述 * @return */ public String getSysDsc(){ try { ResponseEvent event = snmpGet(SnmpConfig.SYS_DSC); if (event!=null&&event.getResponse()!=null){ return event.getResponse().toString().split("=")[4].split("]")[0].trim(); }else { throw new RuntimeException("获取系统描述信息失败"); } } catch (Exception e) { logger.info("获取系统描述信息失败"+e.getMessage()); } return "failure"; } /** * 获取接口数 * @return */ public Integer getIfNumber(){ try { ResponseEvent event = snmpGet(SnmpConfig.IF_NUM); if (event!=null&&event.getResponse()!=null){ String trim = event.getResponse().toString().split("=")[4].split("]")[0].trim(); return Integer.parseInt(trim); }else { throw new RuntimeException("获取接口信息失败"); } } catch (Exception e) { logger.info("获取接口数量失败"+e.getMessage()); } return -1; } /** * 获取cpu核数(n个cpu有n条数据) * @return */ public Integer getCpuNum(){ List<TableEvent> list = snmpWalk(SnmpConfig.CPU_NUM); Integer num=-1; if (list!=null){ num=list.size(); } return num; } public static void main(String[] args) throws IOException { String snmpIp = "127.0.0.1"; Integer snmpPort = 161; SnmpUtil snmpUtil = new SnmpUtil(snmpIp, snmpPort); System.out.println("机器名称"+snmpUtil.getSysName()); System.out.println("磁盘大小 "+ snmpUtil.getDiskSize("devide")); System.out.println("物理地址"+snmpUtil.getMacAddress()); System.out.println("cpu "+snmpUtil.getCpuUsage()); } }
五、结果展示
机器名称localhost 磁盘大小 49.98 cpu 12.67