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

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

首先数据库建表

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

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

  1. 完成监控页面展示

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

  3. 提供json数据GET接口

目录结构如下:

flask_web.py

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>51reboot.com</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: '51Reboot.com'
},

series: [{
name: '51Reboot.com',
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://51reboot.com: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 & 运行起来

监控效果图如下:

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. 【[CQOI2016]手机号码】

    递推版的数位dp 绝对的暴力美学 我们设\(dp[l][i][j][0/1][0/1][0/1]\)表示到了第\(l\)位,这一位上选择的数是\(i\),\(l-1\)位选择的数是\(j\),第一个\ ...

  2. 反向ajax实现

    在过去的几年中,web开发已经发生了很大的变化.现如今,我们期望的是能够通过web快速.动态地访问应用.在这一新的文章系列中,我们学习如何使用反 向Ajax(Reverse Ajax)技术来开发事件驱 ...

  3. Windows下Python3.6安装PIL

    PIL是Python平台事实上的图像处理标准库,需要用到图片的需要导入该模块 一 安装pip https://pip.pypa.io/en/stable/installing/#id8 python ...

  4. 使用appassembler插件生成启动脚本

    appassemblermaven插件可以自动生成跨平台的启动脚本,省去了手工写脚本的麻烦,而且还可以生成jsw的后台运行程序.插件官网:http://www.mojohaus.org/appasse ...

  5. HDU 3367 (伪森林,克鲁斯卡尔)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=3367 Pseudoforest Time Limit: 10000/5000 MS (Java/Oth ...

  6. ActiveRecord初始化,可以实现jfinal系统启动完成后,再建立数据库连接

    1.JFinalConfig的afterJFinalStart方法,可以实现系统启动成功后,调用的方法 2.ActiveRecord 多数据源初始化 package com.meiah.common; ...

  7. MySQL导出表结构方法

    方法一: 以下用的是Navicat Premium,可以换成任意图形化客户端 SELECT COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHAR ...

  8. OpenID Connect Core 1.0(五)使用授权码流验证(下)

    3.1.2.6 验证错误响应(Authentication Error Response) 验证错误响应是一个OAuth 2.0授权错误响应消息,是RP发送授权请求的消息,由OP授权终结点的响应返回. ...

  9. echarts使用方法

    1.引入完整版echarts.min.js. 2.为ECharts准备一个具备大小(宽高)的Dom . <div id="main" style="width: 6 ...

  10. decodeURI、decodeURIComponent 编码方法

    ——摘自<JavaScript高级程序设计> 编码: Global 对象的 encodeURI()和 encodeURIComponent()方法可以对 URI(Uniform Resou ...