java通過snmp協(xié)議獲取物理設備信息
一、SNMP簡介
1、什么是snmp
snmp中文含義是簡單網絡管理協(xié)議,可用完成對計算機、路由器和其他網絡設備的遠程管理和監(jiān)視。利用 SNMP 協(xié)議可以更好地管理和監(jiān)控網絡。管理工作站可以遠程管理所有支持該協(xié)議的網絡設備,如監(jiān)視網絡狀態(tài)、修改網絡設備配置、接收網絡事件警告等。
通俗的講: 我們可用通過snmp協(xié)議獲取物理機、存儲服務器、交換機等設備的信息,本文我們是通過java程序來獲取。
二、SNMP獲取信息步驟
1、開啟SNMP
首先,我們需要在對應的設備上開啟snmp協(xié)議,不同的設備可自行百度開啟的方法。一般設備有對應的管理軟件,可從管理軟件開啟snmp。
開啟snmp需要注意兩個地方:
1、開啟時會讓你設置團體名,一般填pulic就行。
2、端口默認162。
2、MIB文件
舉例說明,獲取任何一類設備信息,都需要該類設備對應的MIB文件,從MIB文件中解析出OID,每個OID對應一個指標。使用cpu核數(shù)對應的OID才能獲取核數(shù)的個數(shù)。
注意:mib文件獲取方式
1、打設備廠商客服電話獲取。
2、去githup下載: mib鏈接,下載后不確定哪個MIB文件是我們需要的,只能用mib瀏覽器自己試唄。
3、MIB瀏覽器
mib瀏覽器就相當于一個客戶端,用來解析mib文件,可以使用該瀏覽器模擬snmp請求獲取對應的指標信息。
我是用瀏覽器先測試請求可不可用,然后在從瀏覽器上拿到oid用java程序獲取。
三、java獲取SNMP信息
1、引入maven
<dependency> <groupId>org.snmp4j</groupId> <artifactId>snmp4j</artifactId> <version>2.8.3</version> </dependency>
2、代碼實現(xiàn)
注:代碼種有snmpGet、snmpWalk兩個方法可用獲取snmp信息。
snmpGet:是傳入的哪個OID的值,就獲取該OID的值。
snmpWalk:獲取OID的子OID的值。舉例說明,傳入的OID是1.2.3.4。 獲取的是1.2.3.4.1,1.2.3.4.2,1.2.3.4.3的OID值。
import lombok.extern.slf4j.Slf4j; 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.*; 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.util.*; @Slf4j public class SnmpUtil2 { private static Snmp snmp = null; private static CommunityTarget target = null; private static Integer port = 162; private static String ip = "10.11.83.10"; private static String communityName = "public"; public static void main(String[] args) throws Exception { new SnmpUtil2(ip, port); List<TableEvent> tableEvents = snmpWalk("1.3.6.1.4.1.2011.2.235.1.1.15.50.1.12"); for (TableEvent tableEvent : tableEvents) { VariableBinding[] vb = tableEvent.getColumns(); if (null == vb) { continue; } System.out.println(vb[0].getOid()+"======"+vb[0].getVariable()); } log.info("=================美麗的分割線==================="); ResponseEvent responseEvent = snmpGet("1.3.6.1.4.1.2011.2.235.1.1.15.50.1.12"); PDU response = responseEvent.getResponse(); for (int i = 0; i < response.size(); i++) { VariableBinding vb1 = response.get(i); System.out.println(vb1.getOid().toString() + "===" + vb1.getVariable()); } } public SnmpUtil2(String intranetDeviceIp, Integer snmpPort) throws IOException { if (snmp == null) { snmp = new Snmp(new DefaultUdpTransportMapping()); snmp.listen(); } //初始化CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString(communityName)); target.setVersion(SnmpConstants.version2c); target.setAddress(new UdpAddress(intranetDeviceIp + "/" + snmpPort)); target.setTimeout(1000); target.setRetries(3); } private static 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) { log.error("snmpGet 異常" + e.getMessage()); } return re; } private static 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); } }
3、常用OID
用枚舉的方式列了一些常用的OID,包括獲取戴爾華為物理機CPU、內存容量及使用率,戴爾存儲集群,FS8600,SCV3000,PS6210的容量及使用率 具體看下代碼注釋
public enum OidEnum { //物理機CPU總核數(shù)、使用率 HostCpuUtilization("1.3.6.1.2.1.25.3.3.1.2","物理機CPU總核數(shù)和使用率","walk"), //物理機內存總量 HostMemoryTotal("1.3.6.1.2.1.25.2.2.0","物理機內存總量","get"), //物理機內存總量(用來計算內存的使用率或者拿到硬盤總量) HostMemoryTotalCalUtil("1.3.6.1.2.1.25.2.3.1.5","物理機內存總量(用來計算內存的使用率或者拿到硬盤總量)","walk"), //物理機內存使用率(用來計算內存的使用率或者拿到硬盤使用量) HostMemoryUsedCalUtil("1.3.6.1.2.1.25.2.3.1.6","物理機內存使用率(用來計算內存的使用率或者拿到硬盤使用量)","walk"), /** * 華為物理機CPU總核數(shù) */ HuaWeiHostCpuTotal("1.3.6.1.4.1.2011.2.235.1.1.15.50.1.12","華為物理機CPU總核數(shù)","walk"), /** * 華為物理機CPU使用率, 單位% */ HuaWeiHostCpuUtilization("1.3.6.1.4.1.2011.2.235.1.1.1.23.0","華為物理機CPU使用率","get"), /** * 華為物理機內存總量 */ HuaWeiHostMemoryTotal("1.3.6.1.4.1.2011.2.235.1.1.16.50.1.4","華為物理機內存總量","walk"), /** * 華為物理機內存使用率, 單位% */ HuaWeiHostMemoryUtilization("1.3.6.1.4.1.2011.2.235.1.1.1.25.0","華為物理機內存總量","get"), //scv3000獲得存儲總量 StorageScv3000Total("1.3.6.1.4.1.674.11000.2000.500.1.2.32.1.3", "scv3000獲得存儲總量(單位GB)","walk"), StorageScv3000Alloc("1.3.6.1.4.1.674.11000.2000.500.1.2.32.1.7", "scv3000獲得存儲分配量(單位GB)","walk"), StorageScv3000Used("1.3.6.1.4.1.674.11000.2000.500.1.2.32.1.6", "scv3000獲得存儲使用量(單位GB)","walk"), //PS6210存儲總量 StoragePs6210Total("1.3.6.1.4.1.12740.1.1.2.1.1.1","PS6210存儲總量(單位MB)","get"), //PS6210存儲空閑量 StoragePs6210Free("1.3.6.1.4.1.12740.1.1.2.1.15.1","PS6210存儲空閑量(單位MB)","get"), //PS6210存儲使用量 StoragePs6210Used("1.3.6.1.4.1.12740.1.1.2.1.2.1","PS6210存儲已使用(單位MB)","get"), //FS8600獲得存儲總量 StorageFs8600Total("1.3.6.1.4.1.674.11000.2000.200.1.38.1","FS8600獲得存儲總量(單位MB)","get"), //FS8600獲得存儲使用量 StorageFs8600Used("1.3.6.1.4.1.674.11000.2000.200.1.38.3","FS8600獲得存儲使用量(單位MB)","get"), //存儲總量 StorageClusterTotal("1.3.6.1.4.1.12124.1.3.1.0", "存儲總量(從磁盤集群獲取)","get"), //存儲已使用量 StorageClusterUsed("1.3.6.1.4.1.12124.1.3.2.0", "存儲使用量(從磁盤集群獲取)","get"); private String oid; private String describe; private String type; OidEnum(String oid, String describe, String type) { this.oid = oid; this.describe = describe; this.type = type; } public String getOid() { return oid; } public String getdDscribe() { return describe; } }
四、SNMPTRAP
SNMP Trap是SNMP的一部分,當被監(jiān)控段出現(xiàn)特定事件,可能是性能問題,甚至是網絡設備接口宕掉等,代理端會給管理站發(fā)告警事件。通過告警事件,管理站可以通過定義好的方法來處理告警。 trap是主動把告警信息推送到一個監(jiān)聽了162端口的接收程序,接收程序接收到的告警是一個OID,我們需要對oid進行翻譯成可讀的告警信息,通過該OID去mib文件找到具體告警的詳情描述。 比較難的是解析MIB文件,我寫了個程序解析mib文件,發(fā)現(xiàn)有些文件解析不成功,也不知道為啥,去外網查了下,說是需要引入其他依賴的mib文件,不過我試了很多次還是不行。
1、接收程序代碼
import java.io.IOException; import lombok.extern.slf4j.Slf4j; import org.snmp4j.CommandResponder; import org.snmp4j.CommandResponderEvent; import org.snmp4j.CommunityTarget; import org.snmp4j.MessageDispatcher; import org.snmp4j.MessageDispatcherImpl; import org.snmp4j.MessageException; import org.snmp4j.PDU; import org.snmp4j.Snmp; import org.snmp4j.log.LogFactory; import org.snmp4j.mp.MPv1; import org.snmp4j.mp.MPv2c; import org.snmp4j.mp.StateReference; import org.snmp4j.mp.StatusInformation; import org.snmp4j.security.Priv3DES; import org.snmp4j.security.SecurityProtocols; import org.snmp4j.smi.*; import org.snmp4j.tools.console.SnmpRequest; import org.snmp4j.transport.AbstractTransportMapping; import org.snmp4j.transport.DefaultTcpTransportMapping; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.snmp4j.util.MultiThreadedMessageDispatcher; import org.snmp4j.util.ThreadPool; @Slf4j public class TrapReceiver implements CommandResponder { public TrapReceiver() { } public static void main(String[] args) { TrapReceiver snmp4jTrapReceiver = new TrapReceiver(); try { snmp4jTrapReceiver.listen(new UdpAddress("10.11.26.219/162")); } catch (IOException e) { System.err.println("Error in Listening for Trap"); System.err.println("Exception Message = " + e.getMessage()); } } /** * This method will listen for traps and response pdu's from SNMP agent. */ public synchronized void listen(TransportIpAddress address) throws IOException { AbstractTransportMapping transport; if (address instanceof TcpAddress) { transport = new DefaultTcpTransportMapping((TcpAddress) address); } else { transport = new DefaultUdpTransportMapping((UdpAddress) address); } ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10); MessageDispatcher mtDispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl()); // add message processing models mtDispatcher.addMessageProcessingModel(new MPv1()); mtDispatcher.addMessageProcessingModel(new MPv2c()); // add all security protocols SecurityProtocols.getInstance().addDefaultProtocols(); SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES()); // Create Target CommunityTarget target = new CommunityTarget(); target.setCommunity(new OctetString("1q2w#E$R5t")); Snmp snmp = new Snmp(mtDispatcher, transport); snmp.addCommandResponder(this); transport.listen(); System.out.println("Listening on " + address); try { this.wait(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } /** * This method will be called whenever a pdu is received on the given port * specified in the listen() method */ public synchronized void processPdu(CommandResponderEvent cmdRespEvent) { log.debug("Received PDU..."); PDU pdu = cmdRespEvent.getPDU(); System.out.println(cmdRespEvent.toString()); System.out.println("接收到的trap信息:[發(fā)送來源="+cmdRespEvent.getPeerAddress()+",snmp版本="+"2"+",團體名="+"public"+", 攜帶的變量="+cmdRespEvent.getPDU().getVariableBindings()+"]"); if (pdu != null) { for (int i = 0; i < pdu.size(); i++) { VariableBinding vb1 = pdu.get(i); // System.err.println(vb1.toString()); } int pduType = pdu.getType(); if ((pduType != PDU.TRAP) && (pduType != PDU.V1TRAP) && (pduType != PDU.REPORT) && (pduType != PDU.RESPONSE)) { pdu.setErrorIndex(0); pdu.setErrorStatus(0); pdu.setType(PDU.RESPONSE); StatusInformation statusInformation = new StatusInformation(); StateReference ref = cmdRespEvent.getStateReference(); try { cmdRespEvent.getMessageDispatcher().returnResponsePdu(cmdRespEvent.getMessageProcessingModel(), cmdRespEvent.getSecurityModel(), cmdRespEvent.getSecurityName(), cmdRespEvent.getSecurityLevel(), pdu, cmdRespEvent.getMaxSizeResponsePDU(), ref, statusInformation); } catch (MessageException ex) { System.err.println("Error while sending response: " + ex.getMessage()); LogFactory.getLogger(SnmpRequest.class).error(ex); } } } } }
2、解析mib文件說明
引入java的兩個jar包,mibble-2.9.3.jar和mibble-mibs-2.9.3.jar,我解析時,遇到有的文件解析成功,有的解析報錯。沒有解析成功的,可用用笨方法,就是用mib瀏覽器查看oid,把所有的告警OID做成一個字典。 因沒有實現(xiàn)成功,具體解析代碼我就不貼了。
到此這篇關于java通過snmp協(xié)議獲取物理設備信息的文章就介紹到這了,更多相關java的snmp協(xié)議獲取信息內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mybatis中Oracle參數(shù)為NULL錯誤問題及解決
這篇文章主要介紹了mybatis中Oracle參數(shù)為NULL錯誤問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12Java BufferedWriter BufferedReader 源碼分析
本文是關于Java BufferedWriter ,BufferedReader 簡介、分析源碼 對Java IO 流深入了解,希望看到的同學對你有所幫助2016-07-07SpringBoot利用@Retryable注解實現(xiàn)接口重試
本文主要介紹了springboot如何利用@Retryable注解實現(xiàn)接口重試功能,文中示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06SpringBoot中使用@Async實現(xiàn)異步任務調用詳解
這篇文章主要介紹了SpringBoot中使用@Async實現(xiàn)異步任務調用詳解,一個可以無需等待被調用函數(shù)的返回值就讓操作繼續(xù)進行的方法(來自百度百科),即程序在順序執(zhí)行時,不等待異步調用的語句返回結果就執(zhí)行后面的程序,需要的朋友可以參考下2023-12-12Java生產者和消費者例子_動力節(jié)點Java學院整理
生產者-消費者(producer-consumer)問題,也稱作有界緩沖區(qū)(bounded-buffer)問題,兩個進程共享一個公共的固定大小的緩沖區(qū)。下文通過實例給大家介紹java生產者和消費者,感興趣的朋友一起學習吧2017-05-05springboot 實現(xiàn)mqtt物聯(lián)網的示例代碼
這篇文章主要介紹了springboot 實現(xiàn)mqtt物聯(lián)網,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03Spring 報錯:元素 "context:component-scan" 的前綴 "context" 未綁定的問題解決
這篇文章主要介紹了Spring 報錯:元素 "context:component-scan" 的前綴 "context" 未綁定的問題解決的相關資料,需要的朋友可以參考下2016-11-11