• Python运维三十六式:用Python写一个简单的监控系统


    市面上有很多开源的监控系统: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服务,实现如下功能:

    1. 完成监控页面展示
    2. 接受POST提交上来的数据
    3. 提供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 就可以看到我们的监控数据了:效果图如下

    chart

    欢迎加入运维开发技术分享QQ群:365534424;数百位业内高手和同行在等你交流

     
     
  • 相关阅读:
    PHP开发调试环境配置(基于wampserver+Eclipse for PHP Developers )
    关于汽车
    PCB 敷铜间距规则(转)
    有同感的话
    kubernetes学习之二进制部署1.16
    kubernetes网络之Flannel
    Kubernetes学习之原理
    Kubernetes学习之基础概念
    Centos7配置Grafana对接OpenLDAP
    Centos7安装OpenLDAP
  • 原文地址:https://www.cnblogs.com/51reboot/p/4006091.html
Copyright © 2020-2023  润新知