使用python编写一个监控使用内存情况的网页界面

环境:centos-7.2

1. 获取内存信息

[root@cml10 web_mem]# cat /proc/meminfo
MemTotal:        1001332 kB
MemFree:          147800 kB
MemAvailable:     257776 kB
Buffers:               0 kB
Cached:           201032 kB

 

说明:

buffers是指用来给块设备做的缓冲大小

cached是用来给文件做缓冲。

MemFree 是空闲内存

 

算法:

已使用内存 = MemTotal - MemFree - Buffers – Cached(centos6)

已使用内存 = MemTotal - MemAvailable(centos7)

2. 存储信息

1. 安装myql

# 安装mysql

[root@cml10 web_mem]# yum  install  -y  mariadb-server  mariadb

 

#启动mysql

[root@cml10 web_mem]# systemctl start mariadb

 

#快速配置,设置root密码

[root@cml10 web_mem]# mysql_secure_installation

 

2. 创建数据库

[root@cml10 web_mem]#  mysql  -uroot  -predhat
mysql> create database  mem;
mysql> use mem;
mysql> create table mem (mem int(10), date int(20));

注意:用time字段表示时间戳,使用int类型

      为简单化,这里的数据库名和表名,还有字段名,都使用mem,含义不同。

 

3. 把获取到的内存信息保存到数据库

1)安装python的mysql库

 [root@cml10 web_mem]#  yum  install  MySQL-python   -y

 

#写一个python调用mysql模块持续观察内存并写入数据库

[root@cml10 web_mem]# cat save_mem.py
#_*_coding:utf-8_*_
 
import time
import MySQLdb as mysql
 
db = mysql.connect(user="root",passwd="redhat",db="mem",host="localhost")
 
db.autocommit(True)  #自动提交模式,把每个查询都当做一个单独的事务自动执行
cur = db.cursor()   #获取一个 “游标”,用来执行sql语句
 
def save_mem():
       f = open("/proc/meminfo")
       total = int(f.readlines()[0].split()[1])
       f = open("/proc/meminfo")
       aviable = int(f.readlines()[2].split()[1])
       mem = (total-aviable)/1024              # unit: MB(把已用内存转成MB单位)
       cur_time = int(time.time())
       sql = 'insert into mem(mem,date) values(%s,%s)' %(mem,cur_time)
       cur.execute(sql)
while True:
       save_mem()
       time.sleep(1)                              # sleep 1 second(等待一秒时间)

 

##编写一个消耗内存的程序:

[root@cml10 web_mem]# consumer_mem.py

s1 = "Today is good   day! "
s2 = s1 * 10000
 
for i in range(1,100):
        for j in range(1,100):
                s2.count(s1)


 

测试:

在一个终端运行save_mem.py, 然后在另一个终端运行consumer_mempy

观察终端1的输出,输出信息是否发生变化。

 

 

3. 展示信息构建web服务

安装flask

使用flask框架构建web服务

 

#安装pip

[root@cml10 web_mem]# cd  /usr/local/src
[root@cml10 src]# wget  --no-check-certificate  https://bootstrap.pypa.io/get-pip.py
[root@cml10 src]# python  get-pip.py

 

#使用pip安装python的flask模块:

[root@cml10 src]# pip  install  flask

编辑后台页面

[root@cml10 web_mem]# flask_web.py
from  flask  import  Flask    #导入flask中的Flask模块=import flask 引用时要flask.Flask
 
app = Flask(__name__)  #产生一个flask实例,即一个网站应用程序。
 
@app.route('/')   #表示访问网站的根目录时,触发函数index()
def index():
       return 'hello flask'
 
if __name__=='__main__':     #指的是只能自己运行的才可以运行网站。
       app.run(host='0.0.0.0', port=9092, debug=True)  
#任意主机可以访问,使用9092端口,启用调试模式

 

 

关闭防火墙,或者进行配置

[root@cml10 web_mem]# systemctl stop firewalld

 

启动flask web服务:

[root@cml10 web_mem]# python   flask_web.py

 

在任何客户端主机的浏览器测试:

http://192.168.5.200:9092

 

使用真实数据渲染图标

1. 在后台程序中获取真实数据

2.   为便于调试,先把真实数据直接打印到后台的终端,然后把后台获取到的数据发送到前端(用json格式)

 

 

  修改后台程序 flask_web.py

[root@cml10 web_mem]# cat flask_web.py
#_*_coding:utf-8_*_
from flask import Flask,render_template
import MySQLdb as mysql
import json
 
con = mysql.connect(user="root",passwd="redhat",db="mem",host="localhost")
con.autocommit(True)
cur = con.cursor()
 
app = Flask(__name__)
 
last_time = 0
 
@app.route('/')
def index():
#     return "cml test"
       return render_template('index.html')
 
@app.route('/cml')
def cml():
       global last_time
       if (last_time > 0):
              sql = 'select * from mem where date > %s' %(last_time/1000)
       else:
              sql = 'select * from mem'
       cur.execute(sql)
       arr = []
       for i in cur.fetchall():
#            print i
              arr.append([i[1]*1000,i[0]])
#     return "ok"
       if (len(arr) > 0):
              last_time = arr[-1][0]
       return json.dumps(arr)
 
if __name__=='__main__':
       app.run(host='0.0.0.0',port=9092,debug=True)

 

动静态文件分离和使用图表展现

使用highchats图标库

测试图表显示

使用示例数据测试图表显示:

 

1. 准备用于显示图片的基础js文件

   jquery.js 和 highstock.js(可以在github网站上搜索下载)

   并把这两个文件保存到网站根目录下的static子目录下

   [root@cml10 web_mem]# mkdir  static
   [root@cml10 web_mem]# cp   jquery.js  highstock.js   static

 

[root@cml10 web_mem]# tree
.
├── flask_web.py
├── save_mem.py
├── static
│   ├── highstock.js
│   └── jquery.js
└── templates
    └── index.html
 
2 directories, 5 files

2. 选择图表模板

选择一个基本的图 single line series

https://www.hcharts.cn/demo/highstock/basic-line

 

[root@cml10 web_mem]# cat templates/index.html
from flask import Flask,render_template
import MySQLdb as mysql
import  json
 
con = mysql.connect(user="root", passwd="redhat", db="mem", host="localhost")
con.autocommit(True)
cur = con.cursor()
 
app = Flask(__name__)
 
@app.route('/')
def index():
       #return 'cml test'
       return render_template('index.html')
 
@app.route('/cml')
def cml():
       sql = 'select * from memory'
       cur.execute(sql)
       arr = []
       for i in cur.fetchall():
              #print i
              arr.append([i[1]*1000, i[0])   #如果写入数据库使没转这里可以,除以1024,以MB为单位
       #return 'ok'
       return json.dumps(arr)
 
if __name__=='__main__':
       app.run(host='0.0.0.0', port=9092, debug=True)

 

测试:(先执行save_mem.py在执行flask_web.py)

[root@cml10 web_mem]# python save_mem.py
[root@cml10 web_mem]# python flask_web.py

##最后出图展示的结果:

1.png


4. 扩展获取增量数据

##修改文件加上判断取最新的值

[root@cml10 web_mem]# cat flask_web.py
#_*_coding:utf-8_*_
from flask import Flask,render_template
import MySQLdb as mysql
import json
 
con = mysql.connect(user="root",passwd="redhat",db="mem",host="localhost")
con.autocommit(True)
cur = con.cursor()
 
app = Flask(__name__)
 
last_time = 0
 
@app.route('/')
def index():
#     return "cml test"
       return render_template('index.html')
 
@app.route('/cml')
def cml():
       global last_time
       if (last_time > 0):
              sql = 'select * from mem where date > %s' %(last_time/1000)
       else:
              sql = 'select * from mem'
       cur.execute(sql)
       arr = []
       for i in cur.fetchall():
#            print i
              arr.append([i[1]*1000,i[0]])
#     return "ok"
       if (len(arr) > 0):
              last_time = arr[-1][0]           ##意思是取最新的值
       return json.dumps(arr)
 
if __name__=='__main__':
       app.run(host='0.0.0.0',port=9092,debug=True)

 

 

##修改index.html文件前端输出自动更新

[root@cml10 web_mem]# cat templates/index.html
<html>
<head>
        <title> my memory monitor </title>
</head>
 
<body>
<div id="container" style="min-width:400px;height:400px"></div>
 
<script src='/static/jquery.js'></script>
<script src='/static/highstock.js'></script>
<script type="text/javascript"> 
     Highcharts.setOptions({ global: { useUTC: false } });  
</script>
<script>
$(function () {
    $.getJSON('/cml', function (cml) {
        $('#container').highcharts('StockChart', {
           chart: {
                            events: {
                                   load:function() {
                                          var series = this.series[0]
                                          setInterval(
                                                 // 表示每隔3000ms(参数2),就执行指定的函数(参数1)
                                                 function(){
                                                        $.getJSON('/cml',function(res){
                                                               $.each(res, function(i,v){
                                                                    series.addPoint(v)
                                                               })
                                                        })
                                                 },
                                                 3000)
                                   }            
                            }
                     },
 
            rangeSelector : {
                selected : 1
            },
            title : {
                text : '服务器以用内存使用情况'
            },
            series : [{
                name : 'AAPL',
                data : cml,
                tooltip: {
                    valueDecimals: 2
                }
            }]
        });
    });
});
 
</script>
</body>
</html>


###注意新写了一遍扩展监控多台主机上的内存情况代码:(需要可以看看,也可以给给意见)

https://blog.51cto.com/legehappy/2043776