市面上有很多开源的监控系统:Cacti、Nagios、Zabbix。感觉都不符合我的需求,为什么不自己做一个呢?

用Python两个小时徒手撸了一个简易的监控系统,给大家分享一下,希望能对大家有所启发。

首先数据库建表

建立一个数据库“falcon”,建表语句如下:

首先我们设计一个web服务,实现如下功能:

  1. 完成监控页面展示

  2. 接受POST提交上来的数据

  3. 提供json数据GET接口

目录结构如下:

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. if __name__ == "__main__":
  31. 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. <div id="container" style="height: 400px"></div>
  46. </body>
  47. </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 & 运行起来

监控效果图如下:

Python 学习交流群:238757010

Python运维三十六式:用Python写一个简单的监控系统的更多相关文章

  1. python运维开发(十六)----Dom&&jQuery

    内容目录: Dom 查找 操作 事件 jQuery 查找 筛选 操作 事件 扩展 Dom 文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它 ...

  2. python运维开发(十八)----Django(二)

    内容目录 路由系统 模版 Ajax model数据库操作,ORM 路由系统 django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对 ...

  3. python运维开发(十)----IO多路复用线程基本使用

    内容目录: python作用域 python2.7和python3.5的多继承区别 IO多路复用 socketserver模块源分析 多线程.进程.协程 python作用域  python中无块级作用 ...

  4. python运维开发(十五)----JavaScript

    内容目录: HTML补充 javascript HTML补充 1.display标签 display的inline-block 属性会自动带3px的宽度 <span style="di ...

  5. python运维开发(十二)----rabbitMQ、pymysql、SQLAlchemy

    内容目录: rabbitMQ python操作mysql,pymysql模块 Python ORM框架,SQLAchemy模块 Paramiko 其他with上下文切换 rabbitMQ Rabbit ...

  6. 学以致用三十六-----弄懂python装饰器

    看了海峰老师讲解的装饰器视频,讲解的非常棒.根据视频,记录笔记如下: 装饰器: 1.本质是函数,用def来定义.功能就是用来(装饰)其他函数,为其他函数添加附加功能 现有两个函数如下, def tes ...

  7. Python学习日记(三十六) Mysql数据库篇 四

    MySQL作业分析 五张表的增删改查: 完成所有表的关系创建 创建教师表(tid为这张表教师ID,tname为这张表教师的姓名) create table teacherTable( tid int ...

  8. python接口自动化测试三十六:数据驱动参数化之paramunittest

    官方文档1.官方文档地址:https://pypi.python.org/pypi/ParamUnittest/2.github源码下载地址:https://github.com/rik0/Param ...

  9. python运维开发(十九)----Django后台表单验证、session、cookie、model操作

    内容目录: Django后台表单验证 CSRF加密传输 session.cookie model数据库操作 Django后台Form表单验证 Django中Form一般有2种功能: 1.用于做用户提交 ...

随机推荐

  1. 【[SCOI2009]迷路】

    大水题一遍 过掉比较繁琐的拆点还是非常开心的 发现每一条边的边权可能不是\(1\),但是边权的范围非常小,同时点数也非常小,只有\(n<=10\),所以我们可以将一个点拆成九个点,之后随便一连边 ...

  2. 随手练——HDU 1251 统计难题

    知识点:前缀树.典型的前缀树模板. 这是用next[26]数组的版本,超内存了.(后来发现,用C++交不会超,G++就会超) #include <iostream> #include &l ...

  3. 3、RabbitMQ-work queues 工作队列

    work queues 工作队列 1.模型图: 为什么会出现 work queues? 前提:使用 simple 队列的时候 我们应用程序在是使用消息系统的时候,一般生产者 P 生产消息是毫不费力的( ...

  4. 进入WinRe(windows恢复环境)

    放个预览图: 方法汇总: 1. 2 . +Shift  3 ”shutdown /r /o“ 或 "bootim" 4 5 启动中强制关闭3次以上 6 狂按F8 (不同的电脑操作不 ...

  5. [Python 多线程] Lock、阻塞锁、非阻塞锁 (八)

    线程同步技术: 解决多个线程争抢同一个资源的情况,线程协作工作.一份数据同一时刻只能有一个线程处理. 解决线程同步的几种方法: Lock.RLock.Condition.Barrier.semapho ...

  6. Linux内存管理学习笔记——内存寻址

    最近开始想稍微深入一点地学习Linux内核,主要参考内容是<深入理解Linux内核>和<深入理解Linux内核架构>以及源码,经验有限,只能分析出有限的内容,看完这遍以后再更深 ...

  7. Android的JNI调用(一)

    Android提供NDK开发包来提供Android平台的C++开发,用来扩展Android SDK的功能.主要包括Android NDK构建系统和JNI实现与原生代码通信两部分. 一.Android ...

  8. 实际SQL案例解决方法整理_LEAD函数相关

    表结构及数据如下: 需求: 将记录按照时间顺序排列,每三条记录为一组,若第二条记录与第一条记录相差5分钟,则删除该记录,若第三条与第二条记录相差5分钟,则删除该记录, 第二组同理,遍历全表,按要求删除 ...

  9. 面试官问你JS基本类型时他想知道什么?

    面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括:1.基本类型(值类型或者原始类型): Number.Boolean.String.NULL.Undefined以及ES6的Sym ...

  10. 20181101noip模拟赛T1

    思路: 我们看到这道题,可以一眼想到一维差分 但这样的复杂度是O(nq)的,显然会T 那么怎么优化呢? 我们会发现,差分的时候,在r~r+l-1的范围内 差分增加的值横坐标相同,纵坐标递增 减小的值横 ...