Python でsnmp プリンタの印刷カウント監視



Pythonでプリンタの印刷カウントをSNMP監視する
ツールを作ってみました。

取得した値は、MySQLのデータベースに保存します。

まずは、SNMPフレームワークをインストールします。
Python SNMP framework
http://pysnmp.sourceforge.net/

#インストール
apt-get install python-mysql*
apt-get install python-pysnmp2

#プリンタカウントのmibはここらしい。
1.3.6.1.2.1.43.10.2.1.4.1.*

#付属のサンプルで値が取得できるか確認
python snmpwalk.py -v 1 192.168.1.1 public 1.3.6.1.2.1.43.10.2.1.4.1
python snmpget.py -v 1 192.168.1.1 public 1.3.6.1.2.1.43.10.2.1.4.1.1

#プリンタカウントのクロール
#毎日17:30に実行-電源が入っていない場合は、0としてカウントする。
#cronに仕込んで、Pythonのスクリプトを動かすことにしました。

#テーブルレイアウト
create table print_count(
ip char(15),
count_date date,
count_total bigint,
count_day int,
primary key(ip,count_date)
) type = myisam, default character set = utf8;

#Pythonのコード

#!/usr/local/bin/python -O
"""
        printer total count gettter.
        use snmp v1 mib 1.3.6.1.2.1.43.10.2.1.4.1.1
        Written by fujishinko, 2008.

"""

# Import PySNMP modules
from pysnmp import asn1, v1
from pysnmp import role

import MySQLdb

def get_count(ip):
        # Create SNMP manager object
        client = role.manager((ip, 161))

        # Pass it a few options
        client.timeout = 1
        client.retries = 5

        # Create a SNMP request&response objects from protocol version
        # specific module.
        try:
         req = v1.GETREQUEST()
         rsp = v1.GETRESPONSE()

        except (NameError, AttributeError):
                print 'Unsupported SNMP protocol version: %s\n%s' % (version, usage)
                return '0'

        # Encode OIDs, encode SNMP request message and try to send
        # it to SNMP agent and receive a response
        try:
                (answer, src) = client.send_and_receive( \
                 req.encode(community='public', \
                 encoded_oids=map(asn1.OBJECTID().encode, ['1.3.6.1.2.1.43.10.2.1.4.1.1'])))
                
        except:
                print ' NoResponse'
                return '0'

        # Decode SNMP response
        rsp.decode(answer)
        
        # Make sure response matches request (request IDs, communities, etc)
        if req != rsp:
         raise 'Unmatched response: %s vs %s' % (str(req), str(rsp))

        # Decode BER encoded Object IDs.
        oids = map(lambda x: x[0], map(asn1.OBJECTID().decode, \
         rsp['encoded_oids']))

        # Decode BER encoded values associated with Object IDs.
        vals = map(lambda x: x[0](), map(asn1.decode, rsp['encoded_vals']))

        # Check for remote SNMP agent failure
        if rsp['error_status']:
         raise 'SNMP error #' + str(rsp['error_status']) + ' for OID #' \
         + str(rsp['error_index'])
        
        ret = '0'
        # Print out results
        for (oid, val) in map(None, oids, vals):
         ret = str(val)
        
        return ret

def insert_count(ip,count_total):
        con = MySQLdb.connect(db="sysad", host="localhost", port=3306,
user="user", passwd="passwd")
        
        cur = con.cursor()
        
        sql = "SELECT IFNULL(MAX(count_total),0) pre_count FROM print_count WHERE ip = '" + ip + "'"
        cur.execute(sql)
        rec = cur.fetchone()
        
        pre_count = 0
        
        while rec != None:
                pre_count = rec[0]
                rec = cur.fetchone()
        
        #トータルカウント未取得の場合は、count_totalに0が設定されている
        if int(count_total) == 0:
                count_total = pre_count
        
        sql = "INSERT INTO print_count (ip,count_date,count_total,count_day) VALUES "
        sql += "("
        sql += "'" + ip + "'"
        sql += ",current_date"
        sql += "," + str(count_total)
        sql += "," + str(int(count_total) - int(pre_count))
        sql += ")"
        
        cur.execute(sql)
        
        cur.close()
        con.close()



if __name__ == '__main__':
        
        #printer ip list file open
        for line in open(’data.txt’,’r’):
                #split printer name,ip address
                printer_name,ip = line.rstrip().split(',')
                #print printer_name, get_count(ip)
                insert_count(ip, get_count(ip))
                


※投稿時、エラーになるので、open近辺は全角に変換してあります。

#プリンタ情報を記載したdata.txt
IPSiO NX920,192.168.1.1
IPSiO NX850,192.168.1.2


SNMPの情報は累計のカウントしか取得できないので、
count_total に累計
count_day に前日との差分カウント
を保存するようにしています。





もどる