Python写的一个简单监控系统

1478次阅读  |  发布于5年以前

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

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

首先数据库建表

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


    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接口

目录结构如下:


    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信息到页面上


    <title>jb51.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: 'jb51.net'
          },

          series: [{
            name: 'jb51.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


    #!/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://jb51.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://jb51.net:8888 就可以看到我们的监控数据了:效果图如下

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8