用Python的Flask框架結(jié)合MySQL寫(xiě)一個(gè)內(nèi)存監(jiān)控程序
這里以監(jiān)控內(nèi)存使用率為例,寫(xiě)的一個(gè)簡(jiǎn)單demo性程序,具體操作根據(jù)51reboot提供的教程寫(xiě)如下。
一、建庫(kù)建表
創(chuàng)建falcon數(shù)據(jù)庫(kù):
mysql> create database falcon character set utf8; Query OK, 1 row affected (0.00 sec)
創(chuàng)建內(nèi)存監(jiān)控使用的表stat,表結(jié)構(gòu)如下:
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;
二、flask web端設(shè)置
首先我們?cè)O(shè)計(jì)一個(gè)web服務(wù),實(shí)現(xiàn)如下功能:
完成監(jiān)控頁(yè)面展示
接受POST提交上來(lái)的數(shù)據(jù)
提供json數(shù)據(jù)GET接口
具體框架結(jié)構(gòu)圖如下:
目錄結(jié)構(gòu)如下:
web ├── flask_web.py └── templates └── mon.html
flask_web代碼如下:
import MySQLdb as mysql import json from flask import Flask, request, render_template app = Flask(__name__) db = mysql.connect(user="361way", passwd="123456", \ 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)
這里使用的匯圖JS為highcharts、highstock ,具體模板頁(yè)面內(nèi)容如下:
[root@91it templates]# cat mon.html
<title>memory monitor</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="{{ url_for('static', filename='jquery.min.js') }}"></script> --> <script type="text/javascript" src="http://ajax.useso.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: 'memory monitor' }, series: [{ name: 'memory monitor', data: data, type: 'spline', tooltip: { valueDecimals: 2 } }] }); }); }); </script> </head> <body> <!-- <script src="{{ url_for('static', filename='highstock.js') }}"></script> --> <script src="http://cdnjs.cloudflare.com/ajax/libs/highstock/2.0.4/highstock.js"></script> <!-- <script src="{{ url_for('static', filename='exporting.js') }}"></script> --> <script src="http://code.highcharts.com/modules/exporting.js"></script> <div id="container" style="height: 400px"></div> </body> </html>
注:這里的JS代碼都直接使用互聯(lián)網(wǎng)上的代碼,如果主機(jī)無(wú)法連接互聯(lián)網(wǎng)的,可以將上面的三段代取取下來(lái),在templates 的同級(jí)目錄創(chuàng)建static 目錄,將下載下來(lái)的三個(gè)文件放到該目錄,刪除模板中三處引用javascript處的代碼,使用當(dāng)前注釋的三段。
三、agent被監(jiān)控端設(shè)置
web展示頁(yè)面完成了,運(yùn)行起來(lái):python flask_web.py 監(jiān)聽(tīng)在8888端口上。我們需要做一個(gè)agent來(lái)采集數(shù)據(jù),并通過(guò)post方法請(qǐng)求flask_web頁(yè)面,將數(shù)據(jù)上傳寫(xiě)入數(shù)據(jù)庫(kù)。這里以監(jiān)控內(nèi)存為例,具體監(jiān)控代碼如下:
#!/usr/bin/env python #coding=utf-8 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): #自動(dòng)獲取mon類(lèi)里的所有g(shù)etXXX方法,用XXX作為key,getXXX()的返回值作為value,構(gòu)造字典 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://test.361way.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 & 在被監(jiān)控主機(jī)上運(yùn)行,如果出于實(shí)驗(yàn)?zāi)康?,想盡快的看到展示效果,可以將time.sleep(60) 改為time.sleep(2) ,這樣每2秒就會(huì)取一次數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù)。
訪問(wèn) http://test.361way.com:8888 就可以看到我們的監(jiān)控?cái)?shù)據(jù)了:效果圖如下
highcharts支持將按時(shí)間拖動(dòng),也支持按指定時(shí)間段查看。并且查看到的圖片可以直接保存為png、jpg或pdf、csv等格式查看。
相關(guān)文章
Python算法練習(xí)之二分查找算法的實(shí)現(xiàn)
二分查找也稱(chēng)折半查找(Binary Search),它是一種效率較高的查找方法。本文將介紹python如何實(shí)現(xiàn)二分查找算法,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2022-06-06一文詳解PyQt5中信號(hào)(Signal)與槽(Slot)
信號(hào)(Signal)與槽(Slot)是Qt中的核心機(jī)制,也是在PyQt編程中對(duì)象之間進(jìn)行通信的機(jī)制。這篇文章主要帶大家了解一下信號(hào)(Signal)與槽(Slot)的使用,需要的可以參考一下2022-12-12Python如何利用pandas讀取csv數(shù)據(jù)并繪圖
這篇文章主要介紹了Python如何利用pandas讀取csv數(shù)據(jù)并繪圖,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07Python中三元運(yùn)算符的簡(jiǎn)潔性及多用途實(shí)例探究
這篇文章主要為大家介紹了Python中三元運(yùn)算符的簡(jiǎn)潔性及多用途實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01Django利用Channels+websocket開(kāi)發(fā)聊天室完整案例
Channels是Django團(tuán)隊(duì)研發(fā)的一個(gè)給Django提供websocket支持的框架,使用它我們可以輕松開(kāi)發(fā)需要長(zhǎng)鏈接的實(shí)時(shí)通訊應(yīng)用,下面這篇文章主要給大家介紹了關(guān)于Django利用Channels+websocket開(kāi)發(fā)聊天室的相關(guān)資料,需要的朋友可以參考下2023-06-06出現(xiàn)module 'queue' has no attrib
這篇文章主要介紹了出現(xiàn)module 'queue' has no attribute 'Queue'問(wèn)題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04python三種數(shù)據(jù)結(jié)構(gòu)及13種創(chuàng)建方法總結(jié)
拿Python來(lái)說(shuō),數(shù)據(jù)結(jié)構(gòu)的概念也是超級(jí)重要,不同的數(shù)據(jù)結(jié)構(gòu),有著不同的函數(shù),供我們調(diào)用,接下來(lái),我們分別來(lái)介紹字符串、列表、字典的創(chuàng)建方法2021-09-09Python實(shí)現(xiàn)識(shí)別圖像中人物的示例代碼
這篇文章主要介紹了通過(guò)face_recognition提供的demo代碼,簡(jiǎn)單調(diào)整了一下,從而實(shí)現(xiàn)識(shí)別圖像中人物的功能,感興趣的可以跟隨小編一起試試2022-01-01