其實(shí)也是在easyhadoop做第二次重構(gòu)的時(shí)候用到了這個(gè)嵌入式的webserver去做服務(wù)器狀態(tài)的監(jiān)控,可以單獨(dú)摘出來(lái)寫個(gè)東西。
思路主要是用python腳本獲取linux服務(wù)器的各種狀態(tài)信息,然后用webserver的方式,以json數(shù)據(jù)發(fā)給http,主控節(jié)點(diǎn)去讀取webserver返回的json,生成系統(tǒng)監(jiān)控報(bào)表。代碼簡(jiǎn)單,開發(fā)和部署都很方便。
用到的主要東西是python的第三方嵌入式web模塊叫cherrypy,之所以選擇cherrypy,主要原因就是開發(fā)快速,學(xué)習(xí)也很快,基本我用了一天多就基本學(xué)會(huì)了怎么來(lái)寫了。當(dāng)然,也可以用python自帶的simpleHTTPserver。不過(guò)那個(gè)確實(shí)太simple了。cherrypy的優(yōu)點(diǎn)在于,多線程,多并發(fā)。又不像Tornado和Django那樣重量級(jí)。因?yàn)槲覀兎祷氐氖莏son,也用不到什么html模板,數(shù)據(jù)庫(kù)的功能。當(dāng)然也可以選擇web.py,不過(guò)相比還是cherrypy更好一點(diǎn)我認(rèn)為,web.py也借鑒了cherrypy不少的思想。
其實(shí)我的集群里都裝了Ganglia, Cacti, Nagios。但是我想看實(shí)時(shí)的圖表生成,就自己寫了這樣一段程序。做自動(dòng)化運(yùn)維的朋友可以當(dāng)一個(gè)參考,添加自己的方法,監(jiān)控別的也是可以的。
主要流程是這樣:
想辦法讀取Linux系統(tǒng)的各種數(shù)據(jù) ?---> ?解析數(shù)據(jù)轉(zhuǎn)成json發(fā)給http服務(wù)器 ?---> ?監(jiān)控服務(wù)器掃描數(shù)據(jù)生成圖表
#!/usr/bin/python
# -*- coding: utf8 -*-
import sys
import cherrypy
import platform
import os
import time
#python 2.4為simplejson,python 2.6以上為json
try:import json
except ImportError:import simplejson as json#假裝做一個(gè)index出來(lái)
class Index(object):#下面這句表示修飾index方法,這個(gè)index方法是暴露給http server的@cherrypy.exposedef index(self):return "hello cherrypy"class Node(object):'''url /node/dist/'''#獲取目標(biāo)機(jī)器的發(fā)行分支,版本號(hào),架構(gòu)類型,主機(jī)名稱等等,返回json@cherrypy.exposedef dist(self):dist_json = ''sysinstaller = ''installer = ''ostype = platform.dist()if(ostype[0] in ['Ubuntu','debian','ubuntu','Debian']):sysinstaller = 'apt-get'installer = 'dpkg'elif(ostype[0] in ['SuSE']):sysinstaller = 'zypper'installer = 'rpm'elif(ostype[0] in ['CentOS', 'centos', 'redhat','RedHat']):sysinstaller = 'yum'installer = 'rpm'machine = platform.machine()hostname = platform.node()dist_json = {'os.system':ostype[0], 'os.version':ostype[1], 'os.release':ostype[2], 'os.sysinstall':sysinstaller, 'os.installer':installer, 'os.arch':machine, 'os.hostname':hostname}return json.dumps(dist_json, sort_keys=False, indent=4, separators=(',', ': '))'''url /node/GetCpuInfo/'''#獲取CPU型號(hào)等,返回json@cherrypy.exposedef GetCpuInfo(self):cpu = []cpuinfo = {}f = open("/proc/cpuinfo")lines = f.readlines()f.close()for line in lines:if line == 'n':cpu.append(cpuinfo)cpuinfo = {}if len(line) < 2: continuename = line.split(':')[0].strip().replace(' ','_')var = line.split(':')[1].strip()cpuinfo[name] = varreturn json.dumps(cpuinfo, sort_keys=False, indent=4, separators=(',', ': '))'''url /node/GetMemInfo/'''#獲取內(nèi)存使用的詳細(xì)信息@cherrypy.exposedef GetMemInfo(self):mem = {}f = open("/proc/meminfo")lines = f.readlines()f.close()for line in lines:if len(line) < 2:continuename = line.split(':')[0]var = line.split(':')[1].split()[0]mem[name] = long(var) * 1024.0mem['MemUsed'] = mem['MemTotal'] - mem['MemFree'] - mem['Buffers'] - mem['Cached']return json.dumps(mem, sort_keys=False, indent=4, separators=(',', ': '))'''url /node/GetLoadAvg//'''#獲取系統(tǒng)負(fù)載的詳細(xì)信息@cherrypy.exposedef GetLoadAvg(self):loadavg = {}f = open("/proc/loadavg")con = f.read().split()f.close()loadavg['lavg_1']=con[0]loadavg['lavg_5']=con[1]loadavg['lavg_15']=con[2]loadavg['nr']=con[3]loadavg['last_pid']=con[4]return json.dumps(loadavg, sort_keys=False, indent=4, separators=(',', ': '))'''url /node/GetIfInfo/eth(x)'''獲取指定網(wǎng)卡的流量信息,這里面有點(diǎn)復(fù)雜@cherrypy.exposedef GetIfInfo(self, interface):dist_json = self.dist()f = open("/proc/net/dev")lines = f.readlines()f.close()intf = {}for line in lines[2:]:con = line.split()#if部分是給centos使用的,centos在流量大的情況下,網(wǎng)卡信息里面字符串會(huì)連上,所以需要單獨(dú)拆分處理,else部分則是ubuntu或者其他系統(tǒng)格式化很好的使用if con[0][-1].isdigit() == True:offset = con[0].split(':')intf['interface'] = str(offset[0])intf['ReceiveBytes'] = str(offset[1])intf['ReceivePackets'] = str(con[1])intf['ReceiveErrs'] = str(con[2])intf['ReceiveDrop'] = str(con[3])intf['ReceiveFifo'] = str(con[4])intf['ReceiveFrames'] = str(con[5])intf['ReceiveCompressed'] = str(con[6])intf['ReceiveMulticast'] = str(con[7])intf['TransmitBytes'] = str(con[8])intf['TransmitPackets'] = str(con[9])intf['TransmitErrs'] = str(con[10])intf['TransmitDrop'] = str(con[11])intf['TransmitFifo'] = str(con[12])intf['TransmitFrames'] = str(con[13])intf['TransmitCompressed'] = str(con[14])intf['TransmitMulticast'] = str(con[15])else:intf['interface'] = str(con[0])intf['ReceiveBytes'] = str(con[1])intf['ReceivePackets'] = str(con[2])intf['ReceiveErrs'] = str(con[3])intf['ReceiveDrop'] = str(con[4])intf['ReceiveFifo'] = str(con[5])intf['ReceiveFrames'] = str(con[6])intf['ReceiveCompressed'] = str(con[7])intf['ReceiveMulticast'] = str(con[8])intf['TransmitBytes'] = str(con[9])intf['TransmitPackets'] = str(con[10])intf['TransmitErrs'] = str(con[11])intf['TransmitDrop'] = str(con[12])intf['TransmitFifo'] = str(con[13])intf['TransmitFrames'] = str(con[14])intf['TransmitCompressed'] = str(con[15])intf['TransmitMulticast'] = str(con[16])return json.dumps(intf, sort_keys=False)#獲取全部網(wǎng)卡的接口和流量信息@cherrypy.exposedef GetIfTraffic(self):ifs = []nettraffic = {}f = open("/proc/net/dev")lines = f.readlines()f.close()for line in lines[2:]:con = line.split()ifname = con[0].split(':')if(ifname[0].strip() != 'lo'):ifs.append(ifname[0].strip())else:continuefor interface in ifs:nettraffic[interface] = self.GetIfInfo( interface)return json.dumps(nettraffic)#獲取硬盤的分區(qū)信息和使用量@cherrypy.exposedef GetHddInfo(self):hdds = []mount = {}file_system = []type = []size = []used = []avail = []used_percent = []mounted_on = []hdds = os.popen('df -lhT | grep -v tmpfs | grep -v boot | grep -v usr | grep -v tmp | sed \'1d;/ /!N;s/\\n//;s/[ ]*[ ]/\\t/g;\'').readlines()for line in hdds:file_system.append(line.replace('\\n','').replace('\\t',' ').split()[0])type.append(line.replace('\\n','').replace('\\t',' ').split()[1])size.append(line.replace('\\n','').replace('\\t',' ').split()[2])used.append(line.replace('\\n','').replace('\\t',' ').split()[3])avail.append(line.replace('\\n','').replace('\\t',' ').split()[4])used_percent.append(line.replace('\\n','').replace('\\t',' ').split()[5])mounted_on.append(line.replace('\\n','').replace('\\t',' ').split()[6])mount['file_system'] = file_systemmount['type'] = typemount['size'] = sizemount['used'] = usedmount['avail'] = availmount['used_percent'] = used_percentmount['mounted_on'] = mounted_ondist_json = json.dumps(mount)return dist_json#獲取CPU的使用量信息,需要系統(tǒng)安裝sysstat支持@cherrypy.exposedef GetCpuDetail(self):dist_json = self.dist()dist = json.loads(dist_json)if(dist['os.system'] in ['CentOS', 'centos', 'redhat', 'RedHat']):if(int(dist['os.version'].split('.')[0]) < 6): #For CentOS onlycmd = 'mpstat 1 1 | sed \'1d;2d;3d;4d\' | awk \'{print "{\\\"user\\\":\\\"\"$3\"\\\",\\\"nice\\\":\\\"\"$4\"\\\",\\\"sys\\\":\\\"\"$5\"\\\",\\\"iowait\\\":\\\"\"$6\"\\\",\\\"irq\\\":\\\"\"$7\"\\\",\\\"soft\\\":\\\"\"$8\"\\\",\\\"steal\\\":\\\"\"$9\"\\\",\\\"idle\\\":\\\"\"$10\"\\\"}"}\''else:cmd = 'mpstat 1 1 | sed \'1d;2d;3d;4d\' | awk \'{print "{\\\"user\\\":\\\"\"$3\"\\\",\\\"nice\\\":\\\"\"$4\"\\\",\\\"sys\\\":\\\"\"$5\"\\\",\\\"iowait\\\":\\\"\"$6\"\\\",\\\"irq\\\":\\\"\"$7\"\\\",\\\"soft\\\":\\\"\"$8\"\\\",\\\"steal\\\":\\\"\"$9\"\\\",\\\"idle\\\":\\\"\"$11\"\\\"}"}\''else:cmd = 'mpstat 1 1 | sed \'1d;2d;3d;4d\' | awk \'{print "{\\\"user\\\":\\\"\"$3\"\\\",\\\"nice\\\":\\\"\"$4\"\\\",\\\"sys\\\":\\\"\"$5\"\\\",\\\"iowait\\\":\\\"\"$6\"\\\",\\\"irq\\\":\\\"\"$7\"\\\",\\\"soft\\\":\\\"\"$8\"\\\",\\\"steal\\\":\\\"\"$9\"\\\",\\\"idle\\\":\\\"\"$11\"\\\"}"}\''cpu = os.popen(cmd).readline().strip()return cpu
if "__main__" == __name__:#服務(wù)器配置settings = {'global': {#綁定端口'server.socket_port' : 60090,#ip地址設(shè)置,覺(jué)得夠安全就用0.0.0.0,否則就單獨(dú)寫那臺(tái)服務(wù)器的ip'server.socket_host': '0.0.0.0','server.socket_file': '','server.socket_queue_size': 100,'server.protocol_version': 'HTTP/1.1','server.log_to_screen': True,'server.log_file': '','server.reverse_dns': False,'server.thread_pool': 200,'server.environment': 'production','engine.timeout_monitor.on': False}}#使用配置和映射路由并啟動(dòng)webservercherrypy.config.update(settings)cherrypy.tree.mount(Index(), '/')cherrypy.tree.mount(Node(), '/node')cherrypy.engine.start()
圖表生成端隨便拿什么語(yǔ)言寫就無(wú)所謂了,反正數(shù)據(jù)都是json格式的。
當(dāng)然,我也用他監(jiān)控hadoop和hbase。代碼加點(diǎn)跟hadoop和hbase相關(guān)的就可以了。
轉(zhuǎn)載于:https://blog.51cto.com/slaytanic/1207929
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的基于嵌入式webserver的服务器状态监控的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。