[转]用python 10min手写一个简易的实时内存监控系统
简易的内存监控系统
本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客
文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star
腾讯视频链接
录制中间网出问题了,重启了一下,所以有两部分
本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理主题思路
- 获取内存信息
- 存储信息
- 展现
- 后续扩展
- 加主机名,monitor部署在多台机器,不直接插数据库
- 通过http请求的方式,一台机器起flask专门存数据monitor
思路图

第一步,我们需要获取内存信息
其实所有的监控项,包括内存数据,都是从文件中读取的,大家执行以下 cat /proc/meminfo就可以看到关于内存的信息,我们关注的是前四行,总内存,空闲内存,缓冲和缓存大小
计算内存占用量公式:
(总内存-空闲内存-缓冲-缓存)/1024Mb
代码呼之欲出 monitor.py
用with打开文件,可以自动关闭,比直接open优雅那么一丢丢
def getMem():
with open('/proc/meminfo') as f:
total = int(f.readline().split()[1])
free = int(f.readline().split()[1])
buffers = int(f.readline().split()[1])
cache = int(f.readline().split()[1])
mem_use = total-free-buffers-cache
print mem_use/1024
while True:
time.sleep(1)
getMem()
执行文件 python monitor.py,每一秒打印一条内存信息
[woniu@teach memory]$ python mointor.py
2920
2919
2919
2919
2919
我们可以写个很搓的测试代码,占用一点内存,看看数据会不会变执行下面代码,能看到内存使用量明显多了几M
# test.py
s = 'akdsakjhdjkashdjkhasjkdhasjkdhkjashdaskjhfoopnnm,ioqouiew'*100000
for i in s:
for j in s:
s.count(j)
获取内存数据done!
第二步存储数据库
我们选用mysql
新建表格,我们需要两个字段,内存和时间 sql呼之欲出,简单粗暴
create memory(memory int,time int)
我们的 monitor.py就不能只打印内存信息了,要存储数据库啦,引入mysql模块,代码如下
import time
import MySQLdb as mysql
db = mysql.connect(user="reboot",passwd="reboot123",db="memory",host="localhost")
db.autocommit(True)
cur = db.cursor()
def getMem():
with open('/proc/meminfo') as f:
total = int(f.readline().split()[1])
free = int(f.readline().split()[1])
buffers = int(f.readline().split()[1])
cache = int(f.readline().split()[1])
mem_use = total-free-buffers-cache
t = int(time.time())
sql = 'insert into memory (memory,time) value (%s,%s)'%(mem_use/1024,t)
cur.execute(sql)
print mem_use/1024
#print 'ok'
while True:
time.sleep(1)
getMem()
比之前的多了拼接sql和执行的步骤,具体过程见视频,大家到数据库里执行一下下面的sql,就能看到我们辛辛苦苦获取的内存数据啦
select * from memory
我们的数据库里数据越来越多,怎么展示呢
我们需要flask 我们看下文件结构
.
├── flask_web.py web后端代码
├── mointor.py 监控数据获取
├── static 静态文件,第三方图表库
│ ├── exporting.js
│ ├── highstock.js
│ └── jquery.js
├── templates
│ └── index.html 展示前端页面
└── test.py 占用内存的测试代码
flask_web就是我们的web服务代码,template下面的html,就是前端展示的文件,static下面是第三方库
flask_web的代码如下
- 提供两个路由
- 根目录渲染文件index.html
- /data路由去数据库插数据,返回json,供画图使用
from flask import Flask,render_template,request
import MySQLdb as mysql
con = mysql.connect(user='reboot',passwd='reboot123',host='localhost',db='memory')
con.autocommit(True)
cur = con.cursor()
app = Flask(__name__)
import json
@app.route('/')
def index():
return render_template('index.html')
@app.route('/data')
def data():
sql = 'select * from memory'
cur.execute(sql)
arr = []
for i in cur.fetchall():
arr.append([i[1]*1000,i[0]])
return json.dumps(arr)
if __name__=='__main__':
app.run(host='0.0.0.0',port=9092,debug=True)
前端index.html highstock的demo页面,copy过来,具体过程见视频
<html>
<head>
<title>51reboot</title>
</head>
<body>
hello world
<div id="container" style="height: 400px; min-width: 310px"></div>
<script src='/static/jquery.js'></script>
<script src='/static/highstock.js'></script>
<script src='/static/exporting.js'></script>
<script>
$(function () {
// 使用当前时区,否则东八区会差八个小时
Highcharts.setOptions({
global: {
useUTC: false
}
});
$.getJSON('/data', function (data) {
// Create the chart
$('#container').highcharts('StockChart', {
rangeSelector : {
selected : 1
},
title : {
text : '内存数据'
},
series : [{
name : '本机内存',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});
});
</script>
</body>
</html>
具体观察数据结构的过程,见视频和demo链接,我们做的 就是把数据库里的数据,拼接成前端画图需要的数据,展现出来
这时候前端就能看到图表啦

我们并不仅限于此,如果想实时的看到内存,应该怎么搞呢
- 查询数据时候增加一个时间戳当限制条件,再次查询时,只返回两次查询之间的增量数据
- 前端动态添加增量结点数据到图表中
- 代码呼之欲出
python
tmp_time = 0
@app.route('/data')
def data():
global tmp_time
if tmp_time>0:
sql = 'select * from memory where time>%s' % (tmp_time/1000)
else:
sql = 'select * from memory'
cur.execute(sql)
arr = []
for i in cur.fetchall():
arr.append([i[1]*1000,i[0]])
if len(arr)>0:
tmp_time = arr[-1][0]
return json.dumps(arr)
前端,3秒查一次增量数据
$.getJSON('/data', function (data) {
// Create the chart
$('#container').highcharts('StockChart', {
chart:{
events:{
load:function(){
var series = this.series[0]
setInterval(function(){
$.getJSON('/data',function(res){
$.each(res,function(i,v){
series.addPoint(v)
})
})
},3000)
}
}
},
rangeSelector : {
selected : 1
},
title : {
text : 'AAPL Stock Price'
},
series : [{
name : 'AAPL',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});
done!两个文件都搞定,double kill!效果 
最终代码直接下载那个木看也行
监控文件monitor.py
import time
import MySQLdb as mysql
db = mysql.connect(user="reboot",passwd="reboot123",db="memory",host="localhost")
db.autocommit(True)
cur = db.cursor()
def getMem():
f = open('/proc/meminfo')
total = int(f.readline().split()[1])
free = int(f.readline().split()[1])
buffers = int(f.readline().split()[1])
cache = int(f.readline().split()[1])
mem_use = total-free-buffers-cache
t = int(time.time())
sql = 'insert into memory (memory,time) value (%s,%s)'%(mem_use/1024,t)
cur.execute(sql)
print mem_use/1024
#print 'ok'
while True:
time.sleep(1)
getMem()
flask
from flask import Flask,render_template,request
import MySQLdb as mysql
con = mysql.connect(user='reboot',passwd='reboot123',host='localhost',db='memory')
con.autocommit(True)
cur = con.cursor()
app = Flask(__name__)
import json
@app.route('/')
def index():
return render_template('index.html')
tmp_time = 0
@app.route('/data')
def data():
global tmp_time
if tmp_time>0:
sql = 'select * from memory where time>%s' % (tmp_time/1000)
else:
sql = 'select * from memory'
cur.execute(sql)
arr = []
for i in cur.fetchall():
arr.append([i[1]*1000,i[0]])
if len(arr)>0:
tmp_time = arr[-1][0]
return json.dumps(arr)
if __name__=='__main__':
app.run(host='0.0.0.0',port=9092,debug=True)
前端
<html>
<head>
<title>51reboot</title>
<meta charset='utf-8'>
</head>
<body>
hello world
<div id="container" style="height: 400px; min-width: 310px"></div>
<script src='/static/jquery.js'></script>
<script src='/static/highstock.js'></script>
<script src='/static/exporting.js'></script>
<script>
$(function () {
// 使用当前时区,否则东八区会差八个小时
Highcharts.setOptions({
global: {
useUTC: false
}
});
$.getJSON('/data', function (data) {
// Create the chart
$('#container').highcharts('StockChart', {
chart:{
events:{
load:function(){
var series = this.series[0]
setInterval(function(){
$.getJSON('/data',function(res){
$.each(res,function(i,v){
series.addPoint(v)
})
})
},3000)
}
}
},
rangeSelector : {
selected : 1
},
title : {
text : '内存数据'
},
series : [{
name : '本机内存',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});
});
</script>
</body>
</html>
代码没有特别注意细节,希望大家喜欢。
[转]用python 10min手写一个简易的实时内存监控系统的更多相关文章
- 用python 10min手写一个简易的实时内存监控系统
简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star 腾讯视频链接 ...
- 10min 手写一个内存监控系统
本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理,及思想.更容易去理解Nagios.Zabbix.Ganglia监控原理,文章最后还有视频教程链接哦,从零敲出来的全过程 思路分为下面几块: ...
- 手写一个简易的IOC
这个小项目是我读过一点Spring的源码后,模仿Spring的IOC写的一个简易的IOC,当然Spring的在天上,我写的在马里亚纳海沟,哈哈 感兴趣的小伙伴可以去我的github拉取代码看着玩 地址 ...
- 来,我们手写一个简易版的mock.js吧(模拟fetch && Ajax请求)
预期的mock的使用方式 首先我们从使用的角度出发,思考编码过程 M1. 通过配置文件配置url和response M2. 自动检测环境为开发环境时启动Mock.js M3. mock代码能直接覆盖g ...
- 手写一个简易的多周期 MIPS CPU
一点前言 多周期 CPU 相比单周期 CPU 以及流水线 CPU 实现来说其实写起来要麻烦那么一些,但是相对于流水线 CPU 和单周期 CPU 而言,多周期 CPU 除了能提升主频之外似乎并没有什么卵 ...
- 手写一个简易版Tomcat
前言 Tomcat Write MyTomcat Tomcat是非常流行的Web Server,它还是一个满足Servlet规范的容器.那么想一想,Tomcat和我们的Web应用是什么关系? 从感性上 ...
- 手写一个虚拟DOM库,彻底让你理解diff算法
所谓虚拟DOM就是用js对象来描述真实DOM,它相对于原生DOM更加轻量,因为真正的DOM对象附带有非常多的属性,另外配合虚拟DOM的diff算法,能以最少的操作来更新DOM,除此之外,也能让Vue和 ...
- 我手写的简易tomcat
前述 自己手写的简易的tomcat,实现了tomcat的基本响应功能,项目代码已经上传到我的Github,刚刚开始学习这里,当前还存在很多问题 项目简述及代码 当我们的Web运行的时候,从浏览器发出的 ...
- 摊牌了!我要手写一个“Spring Boot”
目前的话,已经把 Spring MVC 相关常用的注解比如@GetMapping .@PostMapping .@PathVariable 写完了.我也已经将项目开源出来了,地址:https://gi ...
随机推荐
- UNIX网络编程——并发服务器(TCP)
在迭代服务器中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现. 网络服务器通常用fork来同时 ...
- Android初级教程小案例之单选框RadioGroup与复选框CheckBox
Android里面的单选框和html中的其实是一样的效果.这里用到两个控件:CheckBox和RadioGroup.直接上代码: radio.xml布局文件: <?xml version=&qu ...
- [sersync+rsync] centos6.5 远程文件同步部署记录
针对本地文件的修改,自动同步到远程文件夹,远程备份很方面.研究了下大家的主流同步方案一般是 rsync+inotify和rsync+sersync, 我这里使用sersync的方案,当然大部分都是参照 ...
- 【一天一道LeetCode】#107. Binary Tree Level Order Traversal II
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 来源: htt ...
- TCP/IP入门(4) --应用层
/** 本篇博客由汗青ZJF整理并发布, 转载请注明出处: http://blog.csdn.net/zjf280441589/article/category/1854365 */ TCP/IP中的 ...
- java设计模式---调停者模式
中介者模式(Mediator):用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 通用类图: 举例:在一个公司里面 ...
- (NO.00002)iOS游戏精灵战争雏形(一)
原本想做一个复杂点的平面动作游戏,可以觉得还是有点把握不了.还是先从简单的原型开始吧. 构思中的精灵战争(SpriteWar)是一个类似FC时代的小游戏,可以造兵,可以捕获敌兵.原本还想加上保卫老巢的 ...
- nginx 配置open_cache_file 静态文件的缓存
open_file_cache max=65535 inactive=30s 最多缓存多少个文件,缓存多少时间open_file_cache_min_uses 1 在30S中没有使用到这个配置的次数的 ...
- Leetcode_114_Flatten Binary Tree to Linked List
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42744919 Given a binary tree, f ...
- VS2005宏无法运行的问题(打了补丁MS14-009之后)
VS2005宏无法运行的问题(打了补丁MS14-009之后) 部门很多同事都是使用VS的宏来给源文件添加文件头,给函数.类添加注释等等,大概是14年2月份之后(根据lucifer提供的时间),这些宏突 ...