市面上有很多开源的监控系统:Cacti、nagios、zabbix。感觉都不符合我的需求,为什么不自己做一个呢
用Python两个小时徒手撸了一个简易的监控系统,给大家分享一下,希望能对大家有所启发
首先数据库建表
建立一个数据库“falcon”,建表语句如下:
1 CREATE TABLE `stat` ( 2 `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 3 `host` varchar(256) DEFAULT NULL, 4 `mem_free` int(11) DEFAULT NULL, 5 `mem_usage` int(11) DEFAULT NULL, 6 `mem_total` int(11) DEFAULT NULL, 7 `load_avg` varchar(128) DEFAULT NULL, 8 `time` bigint(11) DEFAULT NULL, 9 PRIMARY KEY (`id`), 10 KEY `host` (`host`(255)) 11 ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
首先我们设计一个web服务,实现如下功能:
- 完成监控页面展示
- 接受POST提交上来的数据
- 提供json数据GET接口
目录结构如下:
web ├── flask_web.py └── templates └── mon.html
flask_web.py
1 import MySQLdb as mysql 2 import json 3 from flask import Flask, request, render_template 4 app = Flask(__name__) 5 db = mysql.connect(user="reboot", passwd="reboot123", 6 db="falcon", charset="utf8") 7 db.autocommit(True) 8 c = db.cursor() 9 10 @app.route("/", methods=["GET", "POST"]) 11 def hello(): 12 sql = "" 13 if request.method == "POST": 14 data = request.json 15 try: 16 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'])) 17 ret = c.execute(sql) 18 except mysql.IntegrityError: 19 pass 20 return "OK" 21 else: 22 return render_template("mon.html") 23 24 @app.route("/data", methods=["GET"]) 25 def getdata(): 26 c.execute("SELECT `time`,`mem_usage` FROM `stat`") 27 ones = [[i[0]*1000, i[1]] for i in c.fetchall()] 28 return "%s(%s);" % (request.args.get('callback'), json.dumps(ones)) 29 30 31 if __name__ == "__main__": 32 app.run(host="0.0.0.0", port=8888, debug=True)
这个template页面是我抄的highstock的示例,mon.html
简单起见我们只展示mem_usage信息到页面上
1 <title>51reboot.com</title> 2 <!DOCTYPE HTML> 3 <html> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 6 <title>Highstock Example</title> 7 8 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> 9 <style type="text/css"> 10 ${demo.css} 11 </style> 12 <script type="text/javascript"> 13 $(function () { 14 $.getJSON('/data?callback=?', function (data) { 15 16 // Create the chart 17 $('#container').highcharts('StockChart', { 18 19 rangeSelector: { 20 inputEnabled: $('#container').width() > 480, 21 selected: 1 22 }, 23 24 title: { 25 text: '51Reboot.com' 26 }, 27 28 series: [{ 29 name: '51Reboot.com', 30 data: data, 31 type: 'spline', 32 tooltip: { 33 valueDecimals: 2 34 } 35 }] 36 }); 37 }); 38 }); 39 </script> 40 </head> 41 <body> 42 <script src="http://cdnjs.cloudflare.com/ajax/libs/highstock/2.0.4/highstock.js"></script> 43 <script src="http://code.highcharts.com/modules/exporting.js"></script> 44 45 46 <div id="container" style="height: 400px"></div> 47 </body> 48 </html>
web展示页面完成了,运行起来:
python flask_web.py 监听在8888端口上
我们需要做一个agent来采集数据,并上传数据库
moniItems.py
1 #!/usr/bin/env python 2 import inspect 3 import time 4 import urllib, urllib2 5 import json 6 import socket 7 8 class mon: 9 def __init__(self): 10 self.data = {} 11 12 def getTime(self): 13 return str(int(time.time()) + 8 * 3600) 14 15 def getHost(self): 16 return socket.gethostname() 17 18 def getLoadAvg(self): 19 with open('/proc/loadavg') as load_open: 20 a = load_open.read().split()[:3] 21 return ','.join(a) 22 23 def getMemTotal(self): 24 with open('/proc/meminfo') as mem_open: 25 a = int(mem_open.readline().split()[1]) 26 return a / 1024 27 28 def getMemUsage(self, noBufferCache=True): 29 if noBufferCache: 30 with open('/proc/meminfo') as mem_open: 31 T = int(mem_open.readline().split()[1]) 32 F = int(mem_open.readline().split()[1]) 33 B = int(mem_open.readline().split()[1]) 34 C = int(mem_open.readline().split()[1]) 35 return (T-F-B-C)/1024 36 else: 37 with open('/proc/meminfo') as mem_open: 38 a = int(mem_open.readline().split()[1]) - int(mem_open.readline().split()[1]) 39 return a / 1024 40 41 def getMemFree(self, noBufferCache=True): 42 if noBufferCache: 43 with open('/proc/meminfo') as mem_open: 44 T = int(mem_open.readline().split()[1]) 45 F = int(mem_open.readline().split()[1]) 46 B = int(mem_open.readline().split()[1]) 47 C = int(mem_open.readline().split()[1]) 48 return (F+B+C)/1024 49 else: 50 with open('/proc/meminfo') as mem_open: 51 mem_open.readline() 52 a = int(mem_open.readline().split()[1]) 53 return a / 1024 54 55 def runAllGet(self): 56 #自动获取mon类里的所有getXXX方法,用XXX作为key,getXXX()的返回值作为value,构造字典 57 for fun in inspect.getmembers(self, predicate=inspect.ismethod): 58 if fun[0][:3] == 'get': 59 self.data[fun[0][3:]] = fun[1]() 60 return self.data 61 62 if __name__ == "__main__": 63 while True: 64 m = mon() 65 data = m.runAllGet() 66 print data 67 req = urllib2.Request("http://51reboot.com:8888", json.dumps(data), {'Content-Type': 'application/json'}) 68 f = urllib2.urlopen(req) 69 response = f.read() 70 print response 71 f.close() 72 time.sleep(60)
nohup python moniItems.py >/dev/null 2>&1 & 运行起来
访问 http://51reboot.com:8888 就可以看到我们的监控数据了:效果图如下
欢迎加入运维开发技术分享QQ群:365534424;数百位业内高手和同行在等你交流