1. 程式人生 > >【Python】SNMP的安裝及Python的呼叫

【Python】SNMP的安裝及Python的呼叫

概述

本文是介紹SNMP在Windows和Linux(Ubuntu)下的安裝,以及通過Python呼叫其介面的文章。

開發環境

  • Python 3.5.1
  • Windows 10 64位,Ubuntu 16.04 64位(虛擬機器)

SNMP

SNMP(簡單網路管理協議),由一組網路管理的標準組成,包含一個應用層協議(application layer protocol)、資料庫模型(database schema)和一組資源物件。該協議能夠支援網路管理系統,用以監測連線到網路上的裝置是否有任何引起管理上關注的情況。

MIB

MIB(Management Information Base),管理資訊庫,由網路管理協議訪問的管理物件資料庫,它包括SNMP可以通過網路裝置的SNMP管理代理進行設定的變數。

Windows下安裝SNMP

之後直接安裝即可,預設安裝路徑是C:\usr。

安裝完後在系統變數下新增:C:\usr\bin,開啟cmd輸入snmpget測試,沒有報錯則說明安裝成功。

Ubuntu下安裝SNMP和配置

下載

$ sudo apt-get install snmpd snmp snmp-mibs-downloader

檢視SNMP服務狀態

$ sudo service snmpd status

簡單測試SNMP服務是否正常

$ snmpwalk -v 2c -c public localhost 1.3.6.1.2.1.1.1
SNMPv2-MIB
::sysDescr.0 = STRING: Linux ubuntu 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64

預設情況下,snmp服務只是對本地開啟,是無法通過遠端獲取該主機的snmp資訊的。所以要設定允許遠端主機訪問

$ sudo netstat -antup | grep 161
udp        0      0 127.0.0.1:161           0.0.0.0:*                           10698/snmpd     

可以看到,161埠只對本機開放(161埠號是snmp服務的埠號),我們需要修改一下,讓snmp服務對外開放。

修改/etc/snmp/snmpd.conf配置檔案,大概在15行,將下面一行註釋掉:agentAddress udp:127.0.0.1:161

重新啟動snmp服務,再通過命令觀察:

$ sudo /etc/init.d/snmpd restart
$ sudo netstat -antup | grep 161
udp        0      0 0.0.0.0:161             0.0.0.0:*                           10763/snmpd 

可以看到SNMP服務已經對外開放了,這樣之後,我們就能在遠端主機進行測試。

由於SNMP預設只能檢視兩個裝置節點,要想檢視所有節點還需要進行一些配置。開啟/etc/snmp/snmpd.conf

sudo vim /etc/snmp/snmpd.conf 

# 在大約45行處新增下面一行
view   systemonly  included   .1
view   systemonly  included   .1.3.6.1.2.1.1
view   systemonly  included   .1.3.6.1.2.1.25.1

最後配置一下mibs,否則可能會報Unknown Object Identifier錯誤。開啟/etc/snmp/snmp.conf,註釋掉mibs:就可以了

sudo vim /etc/snmp/snmp.conf

# As the snmp packages come without MIB files due to license reasons, loading                         
# of MIBs is disabled by default. If you added the MIBs you can reenable
# loading them by commenting out the following line.
#mibs :

Windows下呼叫SNMP檢視其他主機資訊

由於博主使用的是Ubuntu虛擬機器,其IP是192.168.132.130。下面是cmd下通過SNMP檢視該主機的資訊。

開啟cmd,輸入:

snmpwalk -v 2c -c public 192.168.132.130 1.3.6.1.2.1.1.1

返回

SNMPv2-MIB::sysDescr.0 = STRING: Linux ubuntu 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64

成功。

Python程式碼呼叫示例

Python程式碼呼叫系統的snmpwalk指令來查詢裝置資訊。

# coding=utf-8
"""
filename:snmp_test.py

說明:
使用系統的 snmpwalk 來查詢裝置資訊,需要先安裝 snmp
程式碼 Windows 和 Linux 通用

Windows cmd 呼叫示例:snmpwalk -v 2c -c public 127.0.0.1 1.3.6.1.2.1.1.1

Windows cmd 下檢視某主機(192.168.132.130)資訊示例:
snmpwalk -v 2c -c public 192.168.132.130 1.3.6.1.2.1.1.1
"""

import re
import os
import time
import platform

if 'Windows' == platform.system():
    hosts = ['192.168.132.130']
else:
    # 在虛擬機器執行時則檢視本地
    hosts = ['127.0.0.1']

def snmpWalk(host, oid):
    result = os.popen('snmpwalk -v 2c -c public ' + host + ' ' + oid).read().split('\n')[:-1]
    return result

# ------------------------------------------------------------
# 獲取負載資訊
# ------------------------------------------------------------


def getSystem(host):
    system = ':'.join(snmpWalk(host, 'system')[0].split(':')[3:]).strip()
    return system

# ------------------------------------------------------------

# ------------------------------------------------------------
# 獲取負載資訊
# ------------------------------------------------------------


def getLoad(host, loid):
    """系統負載"""
    load_oids = '1.3.6.1.4.1.2021.10.1.3.' + str(loid)
    return snmpWalk(host, load_oids)[0].split(':')[3]


def getLoads(host):
    load1 = getLoad(host, 1)
    load10 = getLoad(host, 2)
    load15 = getLoad(host, 3)
    return load1, load10, load15

# ------------------------------------------------------------

# ------------------------------------------------------------
# 獲取網絡卡流量
# ------------------------------------------------------------


def getNetworkDevices(host):
    """獲取網路裝置資訊"""
    device_mib = snmpWalk(host, 'RFC1213-MIB::ifDescr')
    device_list = []
    for item in device_mib:
        device_list.append(item.split(':')[3].strip())
    return device_list


def getNetworkData(host, oid):
    """獲取網路流量"""
    data_mib = snmpWalk(host, oid)
    data = []
    for item in data_mib:
        byte = float(item.split(':')[3].strip())
        data.append(str(round(byte / 1024, 2)) + ' KB')
    return data


def getNetworkInfo(host):
    device_list = getNetworkDevices(host)
    # 流入流量
    inside = getNetworkData(host, 'IF-MIB::ifInOctets')
    # 流出流量
    outside = getNetworkData(host, 'IF-MIB::ifOutOctets')
    return device_list, inside, outside

# ------------------------------------------------------------


# ------------------------------------------------------------
# 記憶體使用率
# ------------------------------------------------------------

def getSwapTotal(host):
    swap_total = snmpWalk(host, 'UCD-SNMP-MIB::memTotalSwap.0')[0].split(' ')[3]
    return swap_total


def getSwapUsed(host):
    swap_avail = snmpWalk(host, 'UCD-SNMP-MIB::memAvailSwap.0')[0].split(' ')[3]
    swap_total = getSwapTotal(host)
    swap_used = str(round(((float(swap_total) - float(swap_avail)) / float(swap_total)) * 100, 2)) + '%'
    return swap_used


def getMemTotal(host):
    mem_total = snmpWalk(host, 'UCD-SNMP-MIB::memTotalReal.0')[0].split(' ')[3]
    return mem_total


def getMemUsed(host):
    mem_total = getMemTotal(host)
    mem_avail = snmpWalk(host, 'UCD-SNMP-MIB::memAvailReal.0')[0].split(' ')[3]
    mem_used = str(round(((float(mem_total) - float(mem_avail)) / float(mem_total)) * 100, 2)) + '%'
    return mem_used


def getMemInfo(host):
    mem_used = getMemUsed(host)
    swap_used = getSwapUsed(host)
    return mem_used, swap_used

# ------------------------------------------------------------

def main():
    for host in hosts:

        print('=' * 10 + host + '=' * 10)
        start = time.time()
        print("系統資訊")
        system = getSystem(host)
        print(system)

        print("系統負載")
        load1, load10, load15 = getLoads(host)
        print('load(5min): %s ,load(10min): %s ,load(15min): %s' % (load1, load10, load15))

        print("網絡卡流量")
        device_list, inside, outside = getNetworkInfo(host)
        for i, item in enumerate(device_list):
            print('%s : RX: %-15s   TX: %s ' % (device_list[i], inside[i], outside[i]))

        mem_used, swap_used = getMemInfo(host)
        print("記憶體使用率")
        print('Mem_Used = %-15s   Swap_Used = %-15s' % (mem_used, swap_used))

        end = time.time()
        print('run time:', round(end - start, 2), 's')

if __name__ == '__main__':
    main()

Windows下列印:

==========192.168.132.130==========
系統資訊
Linux ubuntu 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64
系統負載
load(5min): 0.03 ,load(10min): 0.03 ,load(15min): 0.00
網絡卡流量
lo : RX: 1861.91 KB TX: 1861.91 KB
Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) : RX: 5733.84 KB TX: 336.49 KB
記憶體使用率
Mem_Used = 93.82% Swap_Used = 0.07%
run time: 2.89 s

Ubuntu下列印:

==========127.0.0.1==========
系統資訊
Linux ubuntu 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64
系統負載
load(5min): 0.02 ,load(10min): 0.02 ,load(15min): 0.00
網絡卡流量
lo : RX: 1861.91 KB TX: 1861.91 KB
Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) : RX: 5738.8 KB TX: 338.76 KB
記憶體使用率
Mem_Used = 94.14% Swap_Used = 0.07%
run time: 0.26 s