這篇文章主要介紹了Python寫的一個簡單監控系統,本文講解了詳細的編碼步驟,並給給出相應的實現代碼,需要的朋友可以參考下
市面上有很多開源的監控系統:Cacti、nagios、zabbix。感覺都不符合我的需求,為什麼不自己做一個呢
用Python兩個小時徒手撸了一個簡易的監控系統,給大家分享一下,希望能對大家有所啟發
首先數據庫建表
建立一個數據庫“falcon”,建表語句如下:
?
1 2 3 4 5 6 7 8 9 10 11 CREATE TABLE `stat` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `host` varchar(256) DEFAULT NULL, `mem_free` int(11) DEFAULT NULL, `mem_usage` int(11) DEFAULT NULL, `mem_total` int(11) DEFAULT NULL, `load_avg` varchar(128) DEFAULT NULL, `time` bigint(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `host` (`host`(255)) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;首先我們設計一個web服務,實現如下功能:
1.完成監控頁面展示
2.接受POST提交上來的數據
3.提供json數據GET接口
目錄結構如下:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 web ├── flask_web.py └── templates └── mon.html [/code] flask_web.py [code] import MySQLdb as mysql import json from flask import Flask, request, render_template app = Flask(__name__) db = mysql.connect(user="reboot", passwd="reboot123", db="falcon", charset="utf8") db.autocommit(True) c = db.cursor() @app.route("/", methods=["GET", "POST"]) def hello(): sql = "" if request.method == "POST": data = request.json try: sql = "INSERT INTO `stat` (`host`,`mem_free`,`mem_usage`,`mem_total`,`load_avg`,`time`) VALUES('%s', '%d', '%d', '%d', '%s', '%d')" % (data['Host'], data['MemFree'], data['MemUsage'], data['MemTotal'], data['LoadAvg'], int(data['Time'])) ret = c.execute(sql) except mysql.IntegrityError: pass return "OK" else: return render_template("mon.html") @app.route("/data", methods=["GET"]) def getdata(): c.execute("SELECT `time`,`mem_usage` FROM `stat`") ones = [[i[0]*1000, i[1]] for i in c.fetchall()] return "%s(%s);" % (request.args.get('callback'), json.dumps(ones)) if __name__ == "__main__": app.run(host="0.0.0.0", port=8888, debug=True)這個template頁面是我抄的highstock的示例,mon.html
簡單起見我們只展示mem_usage信息到頁面上
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <title>.net</title> <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Highstock Example</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <style type="text/css"> ${demo.css} </style> <script type="text/javascript"> $(function () { $.getJSON('/data?callback=?', function (data) { // Create the chart $('#container').highcharts('StockChart', { rangeSelector: { inputEnabled: $('#container').width() > 480, selected: 1 }, title: { text: '.net' }, series: [{ name: '.net', data: data, type: 'spline', tooltip: { valueDecimals: 2 } }] }); }); }); </script> </head> <body> <script src="http://cdnjs.cloudflare.com/ajax/libs/highstock/2.0.4/highstock.js"></script> <script src="http://code.highcharts.com/modules/exporting.js"></script> <div id="container" style="height: 400px"></div> </body> </html>web展示頁面完成了,運行起來:
Python flask_web.py 監聽在8888端口上
我們需要做一個agent來采集數據,並上傳數據庫
moniItems.py
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #!/usr/bin/env python import inspect import time import urllib, urllib2 import json import socket class mon: def __init__(self): self.data = {} def getTime(self): return str(int(time.time()) + 8 * 3600) def getHost(self): return socket.gethostname() def getLoadAvg(self): with open('/proc/loadavg') as load_open: a = load_open.read().split()[:3] return ','.join(a) def getMemTotal(self): with open('/proc/meminfo') as mem_open: a = int(mem_open.readline().split()[1]) return a / 1024 def getMemUsage(self, noBufferCache=True): if noBufferCache: with open('/proc/meminfo') as mem_open: T = int(mem_open.readline().split()[1]) F = int(mem_open.readline().split()[1]) B = int(mem_open.readline().split()[1]) C = int(mem_open.readline().split()[1]) return (T-F-B-C)/1024 else: with open('/proc/meminfo') as mem_open: a = int(mem_open.readline().split()[1]) - int(mem_open.readline().split()[1]) return a / 1024 def getMemFree(self, noBufferCache=True): if noBufferCache: with open('/proc/meminfo') as mem_open: T = int(mem_open.readline().split()[1]) F = int(mem_open.readline().split()[1]) B = int(mem_open.readline().split()[1]) C = int(mem_open.readline().split()[1]) return (F+B+C)/1024 else: with open('/proc/meminfo') as mem_open: mem_open.readline() a = int(mem_open.readline().split()[1]) return a / 1024 def runAllGet(self): #自動獲取mon類裡的所有getXXX方法,用XXX作為key,getXXX()的返回值作為value,構造字典 for fun in inspect.getmembers(self, predicate=inspect.ismethod): if fun[0][:3] == 'get': self.data[fun[0][3:]] = fun[1]() return self.data if __name__ == "__main__": while True: m = mon() data = m.runAllGet() print data req = urllib2.Request("http://3lian.net:8888", json.dumps(data), {'Content-Type': 'application/json'}) f = urllib2.urlopen(req) response = f.read() print response f.close() time.sleep(60) nohup python moniItems.py >/dev/null 2>&1 & 運行起來訪問 http://.net:8888 就可以看到我們的監控數據了:效果圖如下