SNMP 是一種廣泛應用的網路管理協定,用於監控網路裝置的效能。要取得裝置的效能資料,首先需要了解 SNMP 的基礎知識,例如 OID(物件識別碼)的概念。OID 用於唯一標識裝置中的各種資訊,例如 CPU 使用率、記憶體使用量、網路流量等。透過 SNMP,管理系統可以向裝置傳送請求,取得指定的 OID 值。常用的命令列工具 snmpwalk 可以幫助我們快速查詢裝置的 OID 資訊。此外,也可以使用 Python 等程式語言,結合 PySNMP 函式庫,編寫程式碼來讀取和收集效能資料。
使用 SNMP 讀取與收集效能資料
簡介
SNMP(簡單網路管理協定)是一種廣泛使用的網路管理協定,用於監控和管理網路裝置的效能資料。本章節將介紹如何使用 SNMP 讀取和收集網路裝置的效能資料。
介面條目 SNMP OIDs
SNMP 使用 OID(物件識別碼)來識別網路裝置上的各種資訊。表 1-2 列出了與介面條目相關的 SNMP OIDs。
OID 清單
| OID 字串 | OID 名稱 | 描述 |
|---|---|---|
| 1.3.6.1.2.1.2.2.1.1 | ifIndex | 介面的唯一序號。 |
| 1.3.6.1.2.1.2.2.1.2 | ifDescr | 包含介面名稱和其他可用資訊的字串。 |
| 1.3.6.1.2.1.2.2.1.3 | ifType | 代表介面型別的數字,取決於介面的實體鏈路和協定。 |
| 1.3.6.1.2.1.2.2.1.4 | ifMtu | 此介面可以傳輸的最大網路資料報。 |
| 1.3.6.1.2.1.2.2.1.5 | ifSpeed | 介面的估計當前頻寬。如果無法計算當前頻寬,則此數字應包含介面的最大可能頻寬。 |
| 1.3.6.1.2.1.2.2.1.6 | ifPhysAddress | 介面的實體位址,通常是乙太網路介面上的 MAC 位址。 |
| 1.3.6.1.2.1.2.2.1.7 | ifAdminStatus | 此 OID 允許設定介面的新狀態。通常限於以下值:1(啟用)、2(停用)、3(測試)。 |
| 1.3.6.1.2.1.2.2.1.8 | ifOperStatus | 介面的目前狀態。通常限於以下值:1(啟用)、2(停用)、3(測試)。 |
| 1.3.6.1.2.1.2.2.1.9 | ifLastChange | 包含系統啟動時間(sysUpTime)讀取值,當此介面進入其目前狀態時。如果介面在上次系統重新初始化之前進入此狀態,則可能設定為零。 |
| 1.3.6…(省略) |
詳細解說
這些 OID 提供有關網路裝置介面的詳細資訊,包括其狀態、頻寬、傳輸和接收的資料量等。
SNMP 認證
早期的 SNMP 實作使用簡單的認證機制,包括唯讀和讀寫兩種社群字串。管理系統必須使用其中一個有效的社群字串進行認證,才能對代理程式發出命令。
從命令列查詢 SNMP
在撰寫應用程式之前,可以使用命令列工具查詢 SNMP,以驗證 SNMP 代理程式傳回的資訊是否正確。Net-SNMP-Utils 軟體包提供了多種命令列工具,可以用於查詢和設定 SNMP 物件。
安裝 Net-SNMP-Utils
在根據 RedHat 的系統上,可以使用以下命令安裝:
$ sudo yum install net-snmp-utils
在根據 Debian 的系統上,可以使用以下命令安裝:
$ sudo apt-get install snmp
使用 snmpwalk 命令
snmpwalk 命令是一個非常有用的工具,它接受一個 OID 節點作為引數,並嘗試發現所有子節點 OID。該命令使用 SNMP 操作 getnext,傳回樹中的下一個節點,有效地允許您遍歷從指定節點開始的整個子樹。
程式碼範例
snmpwalk -v 1 -c public localhost .1.3.6.1.2.1.2.2
內容解密:
此命令使用 snmpwalk 對本地主機上的 SNMP 代理程式進行查詢,檢索與介面條目相關的資訊。其中,-v 1 指定 SNMP 版本,-c public 指定社群字串,localhost 是目標主機,.1... 是要查詢的 OID 節點。
使用SNMP讀取與收集效能資料
SNMP(簡單網路管理協定)是一種用於管理和監控網路裝置的標準協定。在本章中,我們將探討如何使用SNMP來讀取和收集網路裝置的效能資料。
SNMP基礎
SNMP允許管理站(Manager)與被管理裝置(Agent)之間進行通訊,以收集和修改被管理裝置的資訊。SNMP使用OID(物件識別符號)來唯一標識被管理裝置中的每個物件。
使用snmpwalk命令收集資料
snmpwalk是一個用於透過SNMP協定檢索網路實體的資訊的命令列工具。以下是使用snmpwalk命令的一個範例:
$ snmpwalk –v2c -c public -On 192.168.1.68
內容解密:
-v2c指定使用的SNMP版本為v2c。-c public設定community字串為public,這是用於驗證的密碼。-On表示以數字形式顯示OID。192.168.1.68是被管理裝置的IP地址。
分析snmpwalk輸出的結果
執行snmpwalk命令後,將輸出被管理裝置的多個OID及其對應的值。以下是輸出的部分內容:
.1.3.6.1.2.1.1.1.0 = STRING: Linux fedolin.example.com 2.6.32.11-99.fc12.i686 #1 SMP Mon Apr 5 16:32:08 EDT 2010 i686
.1.3.6.1.2.1.1.2.0 = OID: .1.3.6.1.4.1.8072.3.2.10
...
.1.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1
.1.3.6.1.2.1.2.2.1.1.2 = INTEGER: 2
...
內容解密:
- 第一行顯示了系統的描述資訊,包括作業系統型別、版本和主機名稱。
.1.3.6.1.2.1.1.2.0表示系統物件ID,通常用於識別裝置型別。- 後續的輸出顯示了網路介面的索引、名稱、型別等資訊,如
.1.3.6.1.2.1.2.2.1.1.x和.1.3.6.1.2.1.2.2.1.2.x。
OID的意義與查詢
OID是SNMP中用於識別被管理物件的唯一識別符號。根據輸出結果,可以查詢相關OID的含義。例如:
.1.3.6.1.2.1.1對應於系統資訊群組,提供了系統的基本資訊,如系統描述、聯絡資訊等。.1.3.6.1.2.1.2對應於網路介面群組,提供了網路介面的詳細資訊,如介面數量、介面狀態等。
內容解密:
- 使用SNMP MIB瀏覽器或相關檔案可以查詢OID的具體含義。
- 瞭解OID的含義有助於更好地理解和管理網路裝置。
練習與應用
嘗試使用提供的表格(Tables 1-1 和 1-2)來識別輸出的OID,並理解其含義。這有助於更深入地理解SNMP的工作原理和網路裝置的管理。
使用Python與SNMP進行效能資料收集
簡介
SNMP(簡單網路管理協定)是一種廣泛使用的網路管理協定,用於監控和管理網路裝置。在本章中,我們將探討如何使用Python與SNMP來收集網路裝置的效能資料。
設定應用程式
首先,我們需要設定應用程式的組態檔。我們將使用Windows INI-style的組態檔,因為它簡單易用。Python內建了組態檔解析模組,因此使用起來也很方便。
組態檔範例
[system_1]
description=My Laptop
address=192.168.1.68
port=161
communityro=public
[check_1]
description=WLAN incoming traffic
oid=1.3.6.1.2.1.2.2.1.10.3
system=system_1
[check_2]
description=WLAN incoming traffic
oid=1.3.6.1.2.1.2.2.1.16.3
system=system_1
建立SnmpManager類別
我們將建立一個名為SnmpManager的類別,用於管理SNMP裝置。該類別將具有兩個方法:add_system和add_check。
SnmpManager類別定義
import sys
from ConfigParser import SafeConfigParser
class SnmpManager:
def __init__(self):
self.systems = {}
def add_system(self, id, descr, addr, port, comm_ro):
self.systems[id] = {'description': descr,
'address': addr,
'port': int(port),
'communityro': comm_ro,
'checks': {}
}
def add_check(self, id, oid, descr, system):
oid_tuple = tuple([int(i) for i in oid.split('.')])
self.systems[system]['checks'][id] = {'description': descr,
'oid': oid_tuple,
}
使用PySNMP函式庫
在本專案中,我們將使用PySNMP函式庫,它是一個純Python實作的SNMP函式庫,不依賴任何預編譯的函式庫。
安裝PySNMP函式庫
您可以使用以下命令安裝PySNMP函式庫:
$ sudo yum install pysnmp
$ sudo yum install python-pyasn1
或者使用Python套件管理器(PiP)安裝:
$ sudo pip install pysnmp
$ sudo pip install pyasn1
SNMP GET命令
SNMP GET命令用於從SNMP代理程式取得特定的OID值。
SNMP GET命令範例
>>> from pysnmp.entity.rfc3413.oneliner import cmdgen
>>> cg = cmdgen.CommandGenerator()
>>> comm_data = cmdgen.CommunityData('my-manager', 'public')
>>> transport = cmdgen.UdpTransportTarget(('192.168.1.68', 161))
>>> variables = (1, 3, 6, 1, 2, 1, 1, 1, 0)
>>> errIndication, errStatus, errIndex, result = cg.getCmd(comm_data, transport, variables)
>>> print errIndication
None
>>> print errStatus
0
>>> print errIndex
0
>>> print result
[(ObjectName('1.3.6.1.2.1.1.1.0'), OctetString('Linux fedolin.example.com
2.6.32.11-99.fc12.i686 #1 SMP Mon Apr 5 16:32:08 EDT 2010 i686'))]
>>>
內容解密:
在這個範例中,我們使用了PySNMP函式庫的CommandGenerator類別來建立一個SNMP GET命令。首先,我們匯入了必要的模組並建立了一個CommandGenerator物件。然後,我們建立了一個CommunityData物件,用於指定SNMP共同體字串。接著,我們建立了一個UdpTransportTarget物件,用於指定SNMP代理程式的位址和埠號。最後,我們呼叫了getCmd方法來執行SNMP GET命令,並列印出了結果。
在結果中,我們可以看到OID值為1.3.6.1.2.1.1.1.0的對應值是一個字串,包含了Linux系統的版本資訊。
使用 SNMP 讀取與收集效能資料
SNMP GET 命令的執行細節
在 PySNMP 中,SNMP GET 命令對應到 getCmd() 方法的呼叫。當我們發起 SNMP GET 請求時,需要準備三個主要物件:CommunityData、UdpTransportTarget 和變數元組。
初始化 CommunityData 物件
當我們初始化 CommunityData 物件時,需要提供兩個字串:社群字串(community string)和代理或管理員安全名稱字串。在大多數情況下,安全名稱可以是任意字串。此外,還可以指定使用的 SNMP 版本(預設為 SNMP v2c)。如果需要查詢版本 1 裝置,可以使用以下命令:
comm_data = cmdgen.CommunityData('my-manager', 'public', mpModel=0)
Transport 物件的初始化
UdpTransportTarget 物件使用包含完整網域名稱或 IP 位址字串和整數埠號的元組進行初始化。
OID 的表示
最後一個引數是 OID,以包含所有節點 ID 的元組表示。因此,在讀取組態專案時,我們需要將點分隔的字串轉換為元組。
呼叫 getCmd() 方法
最後,我們呼叫 getCmd() 方法,該方法實作了 SNMP GET 命令,並將這三個物件作為引數傳遞。該命令傳回一個元組,每個元素描述如下:
| 元組元素 | 描述 |
|---|---|
| errIndication | 如果此字串不為空,則表示 SNMP 引擎錯誤。 |
| errStatus | 如果此元素評估為 True,則表示 SNMP 通訊中發生錯誤;錯誤物件由 errIndex 元素指示。 |
| errIndex | 如果 errStatus 指示發生錯誤,則可以使用此欄位查詢導致錯誤的 SNMP 物件。結果陣列中的物件位置是 errIndex-1。 |
| result | 此元素包含所有傳回的 SNMP 物件元素的列表。每個元素是一個元組,包含物件名稱和物件值。 |
SNMP SET 命令的使用
SNMP SET 命令在 PySNMP 中對應到 setCmd() 方法的呼叫。所有引數都相同;唯一的區別是變數部分現在包含一個元組:OID 和新值。
示例:嘗試修改唯讀物件
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto import rfc1902
cg = cmdgen.CommandGenerator()
comm_data = cmdgen.CommunityData('my-manager', 'public')
transport = cmdgen.UdpTransportTarget(('192.168.1.68', 161))
variables = ((1, 3, 6, 1, 2, 1, 1, 1, 0), rfc1902.OctetString('new system description'))
errIndication, errStatus, errIndex, result = cg.setCmd(comm_data, transport, variables)
結果分析
print(errIndication) # None
print(errStatus) # 6
print(errIndex) # 1
print(errStatus.prettyPrint()) # noAccess(6)
print(result) # [(ObjectName('1.3.6.1.2.1.1.1.0'), OctetString('new system description'))]
在這個例子中,我們嘗試寫入唯讀物件,導致錯誤。值得注意的是,我們需要將字串轉換為 SNMP 物件型別;否則,它們不會作為有效的引數傳遞。
SNMP GETNEXT 命令的使用
SNMP GETNEXT 命令實作為 nextCmd() 方法。語法和用法與 getCmd() 相同;唯一的區別是結果是指定 OID 節點的直接子節點的物件列表。
示例:查詢 SNMP 系統 OID 的直接子節點
from pysnmp.entity.rfc3413.oneliner import cmdgen
cg = cmdgen.CommandGenerator()
comm_data = cmdgen.CommunityData('my-manager', 'public')
transport = cmdgen.UdpTransportTarget(('192.168.1.68', 161))
variables = (1, 3, 6, 1, 2, 1, 1)
errIndication, errStatus, errIndex, result = cg.nextCmd(comm_data, transport, variables)
結果分析
for object in result:
print(object)
輸出結果為:
[(ObjectName('1.3.6.1.2.1.1.1.0'), OctetString('Linux fedolin.example.com 2.6.32.11-99.fc12.i686 #1 SMP Mon Apr 5 16:32:08 EDT 2010 i686'))]
[(ObjectName('1.3.6.1.2.1.1.2.0'), ObjectIdentifier('1.3.6.1.4.1.8072.3.2.10'))]
[(ObjectName('1.3.6.1.2.1.1.3.0'), TimeTicks('340496'))]
[(ObjectName('1.3.6.1.2.1.1.4.0'), OctetString('Administrator ([email protected])'))]
[(ObjectName('1.3.6.1.2.1.1.5.0'), OctetString('fedolin.example.com'))]
[(ObjectName('1.3.6.1.2.1.1.6.0'), OctetString('MyLocation, MyOrganization, MyStreet, MyCity, MyCountry'))]
此圖示呈現了 SNMP GETNEXT 命令的執行結果:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title SNMP網路裝置效能資料收集
package "資料庫架構" {
package "應用層" {
component [連線池] as pool
component [ORM 框架] as orm
}
package "資料庫引擎" {
component [查詢解析器] as parser
component [優化器] as optimizer
component [執行引擎] as executor
}
package "儲存層" {
database [主資料庫] as master
database [讀取副本] as replica
database [快取層] as cache
}
}
pool --> orm : 管理連線
orm --> parser : SQL 查詢
parser --> optimizer : 解析樹
optimizer --> executor : 執行計畫
executor --> master : 寫入操作
executor --> replica : 讀取操作
cache --> executor : 快取命中
master --> replica : 資料同步
note right of cache
Redis/Memcached
減少資料庫負載
end note
@enduml
詳細解析此圖示
此圖示展示了 SNMP GETNEXT 命令的流程。首先,SNMP GETNEXT 命令會查詢指定 OID 的直接子節點。接著,傳回這些子節點的物件列表。每個物件都包含名稱和值,方便管理和監控網路裝置。
程式碼段作用與邏輯解析:
variables = (1, 3, 6, 1, 2, 1, 1)
errIndication, errStatus, errIndex, result = cg.nextCmd(comm_data, transport, variables)
此程式碼段的作用是使用 nextCmd() 方法查詢 OID (1, 3, 6, 1, 2, 1, 1) 的直接子節點。其中,variables 指定了要查詢的 OID,而 nextCmd() 方法則執行查詢並傳回結果。
邏輯解析:
variables元組包含了 OID 的各個部分,這些部分組合起來形成完整的 OID。nextCmd()方法接收comm_data、transport和variables作為引數,分別代表社群資料、傳輸目標和查詢的 OID。- 方法傳回四個值:
errIndication、errStatus、errIndex和result,分別表示錯誤指示、錯誤狀態、錯誤索引和查詢結果。 - 結果
result是物件列表,每個物件包含名稱和值,用於描述查詢到的 OID 直接子節點的資訊。