用Python寫一個簡單的監控系統

發表於 2014年9月21日root

市面上有很多開源的監控系統:Cacti、nagios、zabbix。感覺都不符合我的需求,爲什麼不自己做一個呢

Python兩個小時徒手擼了一個簡易的監控系統,給大家分享一下,希望能對大家有所啓發

首先數據庫建表

建立一個數據庫“falcon”,建表語句如下:

MySQL

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;

1

2

3

4

5

6

7

8

9

10

11

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;

首先我們設計一個web服務,實現如下功能:

  1. 完成監控頁面展示

  2. 接受POST提交上來的數據

  3. 提供json數據GET接口

目錄結構如下:

web ├── flask_web.py └── templates    └── mon.html

1

2

3

4

web

├── flask_web.py

└── templates

└── mon.html

flask_web.py

flask_web.py

Python

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)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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信息到頁面上

mon.html

XHTML

<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>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

<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

moniItems.py

Python

#!/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)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

#!/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 & 運行起來

訪問 http://51reboot.com:8888 就可以看到我們的監控數據了:效果圖如下

chart 300x200 Python運維三十六式:用Python寫一個簡單的監控系統

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章