研究了一個腳本,其主要目的是:基于 Python 編程語言來監(jiān)控服務(wù)器的 CPU、內(nèi)存、/目錄、/appslog、/bigdata目錄使用率以及網(wǎng)卡接收和發(fā)送情況。
該腳本部署場景分為:服務(wù)端和客戶端。
服務(wù)端:一臺固定 IP 地址的服務(wù)器
客戶端:N 臺指定固定 IP 地址的服務(wù)器
服務(wù)端腳本:
#-*-coding:utf-8-*- importio importos importsys importlogging fromloggingimporthandlers importMySQLdb importsmtplib fromemail.mime.textimportMIMEText fromemail.headerimportHeader fromemail.utilsimportformataddr importrequests,json importdatetime importtime importshutil,re importuuid importsocket importSocketServer ifsys.getdefaultencoding()!='utf-8': reload(sys) sys.setdefaultencoding('utf-8') classLogger(object): level_relations={ 'debug':logging.DEBUG, 'info':logging.INFO, 'warning':logging.WARNING, 'error':logging.ERROR, 'crit':logging.CRITICAL }#日志級別關(guān)系映射 def__init__(self,logname,level='info',when='D',backCount=10,fmt='%(asctime)s-%(pathname)s[line:%(lineno)d]-%(levelname)s:%(message)s'): CURRENT_DIR=os.path.dirname(__file__) LOG_FILE=os.path.abspath(os.path.join(CURRENT_DIR,logname)) self.logger=logging.getLogger(LOG_FILE) format_str=logging.Formatter(fmt)#設(shè)置日志格式 self.logger.setLevel(self.level_relations.get(level))#設(shè)置日志級別 sh=logging.StreamHandler()#往屏幕上輸出 sh.setFormatter(format_str)#設(shè)置屏幕上顯示的格式 th=handlers.TimedRotatingFileHandler( filename=LOG_FILE,when=when,backupCount=backCount,encoding='utf-8')#往文件里寫入#指定間隔時間自動生成文件的處理器 #實例化TimedRotatingFileHandler #interval是時間間隔,backupCount是備份文件的個數(shù),如果超過這個個數(shù),就會自動刪除,when是間隔的時間單位,單位有以下幾種: #S秒 #M分 #H小時、 #D天、 #W每星期(interval==0時代表星期一) #midnight每天凌晨 th.setFormatter(format_str)#設(shè)置文件里寫入的格式 #self.logger.addHandler(sh)#把對象加到logger里 ifnotself.logger.handlers: self.logger.addHandler(th) classAnalysis(object): defbuildMsg(self,msg): print('構(gòu)造預(yù)警信息'+str(msg)) icount=0 if(float(msg[4])>90): icount+=1 CPU="> CPU預(yù)警:使用率高于90%,使用"+str(msg[4])+"% " else: CPU="" if(float(msg[5])>90): icount+=1 mem=">內(nèi)存預(yù)警:使用率高于90%,使用"+str(msg[5])+"% " else: mem="" if(float(msg[6])>85): icount+=1 disk_root=">磁盤根目錄預(yù)警:使用率高于85%,使用"+str(msg[6])+"% " else: disk_root="" if(float(msg[7])>85): icount+=1 disk_appslog=">業(yè)務(wù)磁盤預(yù)警:使用率高于85%,使用"+str(msg[7])+"% " else: disk_appslog="" if(float(msg[8])>3000): icount+=1 networkRecv=">網(wǎng)卡10秒內(nèi)接收數(shù)據(jù)預(yù)警:接收數(shù)據(jù)大于4000M,接收"+str(msg[8])+"M " else: networkRecv="" if(float(msg[9])>3000): icount+=1 networkSend=">網(wǎng)卡10秒內(nèi)發(fā)送數(shù)據(jù)預(yù)警:發(fā)送數(shù)據(jù)大于4000M,發(fā)送"+str(msg[9])+"M " else: networkSend="" s=alarmName+" "+msg[2]+":"+msg[3]+" "+CPU+mem+disk_root+disk_appslog+networkRecv+networkSend #print(s) log.logger.info('預(yù)警信息:'+s) #發(fā)送預(yù)警 if(icount>0): #發(fā)送預(yù)警郵件、企業(yè)微信 ifmailconf==1: self.send_mail(s,msg[3]) ifwxconf==1: self.send_WX(s) defsend_mail(self,content,ip): smtpserver='smtp.163.com' mail_user="xxx@163.com" mail_pass="passwordxxx" mail_res=["xxx@163.com","xxx@163.com","xxx@163.com","xxx@163.com","xxx@163.com","xxx@163.com","xxx@163.com"] sub=time.strftime("%Y-%m-%d%H:%M:%S",time.localtime()) msg=MIMEText(sub+" "+content,_subtype='plain',_charset='utf-8') msg['Subject']=Header(alarmName+':'+ip,'utf-8') #msg['From']=Header("系統(tǒng)預(yù)警",'utf-8') msg['From']=formataddr(pair=('設(shè)備預(yù)警',mail_user)) msg['To']=','.join(mail_res) smtp=smtplib.SMTP() smtp.connect(smtpserver) smtp.starttls() smtp.login(mail_user,mail_pass) smtp.sendmail(mail_user,mail_res,msg.as_string()) smtp.quit() defsend_WX(self,msg): headers={"Content-Type":"text/plain"} #s="服務(wù)器預(yù)警:{},驗證碼{}".format({str(printCode)},{str(verifyCode)}) data={ "msgtype":"text", "text":{ "content":msg, } } r=requests.post( url='企業(yè)微信機(jī)器人地址(需要根據(jù)實際機(jī)器人地址配置)', headers=headers,json=data) print(r.text) defWrite_to_Mysql_alarm(self,valuelist): #log=Logger('all.log',level='debug') #業(yè)務(wù)監(jiān)控:id,project,tpye,exceptiontype,details(xx,大數(shù)據(jù),無es進(jìn)程/es集群不健康,) try: db=MySQLdb.connect("xxx","xxx","xxx","xxx",charset='utf8') log.logger.info("數(shù)據(jù)庫連接成功") except: log.logger.info("數(shù)據(jù)庫連接失敗") #創(chuàng)建游標(biāo) cursor=db.cursor() uid=uuid.uuid1() result=0 sql='' try: sql='insertintotest_serverresourcealarmvalues(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)' #val=(str(uid),valuelist[1],valuelist[2],valuelist[3],valuelist[4],valuelist[5],valuelist[6],'',valuelist[7],valuelist[8],valuelist[9],valuelist[10],'','','') val=(str(uid),valuelist[2],valuelist[3],valuelist[4],valuelist[5],valuelist[6],valuelist[7],'',valuelist[8],valuelist[9],valuelist[10],'','','') cursor.execute(sql,val) db.commit() log.logger.error('設(shè)備預(yù)警信息已入庫!') #發(fā)送企業(yè)微信預(yù)警信息 self.buildMsg(valuelist) except: into=sys.exc_info() #log.logger.error('插入數(shù)據(jù)失敗!') log.logger.error('設(shè)備預(yù)警信息入庫失敗!'+str(into)) result=0 #str=self.obj_to_string(sys.exc_info(),self) print('error',into) #關(guān)閉游標(biāo) db.close() returnresult defWrite_to_Mysql_temp(self,valuelist): #打開數(shù)據(jù)庫連接 #db=MySQLdb.connect("xxx","xxx","xxx","xxx",charset='utf8') try: db=MySQLdb.connect("xxx","xxx","xxx","xxx",charset='utf8') log.logger.info("數(shù)據(jù)庫連接成功") except: log.logger.info("數(shù)據(jù)庫連接失敗") #使用cursor()方法獲取操作游標(biāo) cursor=db.cursor() uid=uuid.uuid1() result=0 try: sql='insertintotest_serverresourcetempvalues(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)' val=(str(uid),valuelist[2],valuelist[3],valuelist[4],valuelist[5],valuelist[6],valuelist[7],'',valuelist[8],valuelist[9],valuelist[10],'','','') cursor.execute(sql,val) db.commit() result=1 log.logger.info("臨時表sql執(zhí)行狀態(tài):"+str(result)) except: into=sys.exc_info() result=0 print(into) log.logger.info('臨時表sql執(zhí)行失敗:'+str(into)) #關(guān)閉數(shù)據(jù)庫連接 db.close() returnresult classMyServer(SocketServer.BaseRequestHandler): defhandle(self): conn=self.request log.logger.info('...connectedfrom{}'.format(self.client_address)) #print('1多線程監(jiān)控') Flag=True whileFlag: data=conn.recv(1024) #print(data) iflen(data)>10: log.logger.info('接收到的客戶端數(shù)據(jù):'+data) conn.sendall('1') sub=data.strip(' ') str=sub.split('|') #print(str) a=Analysis() #報警信息入庫,#將監(jiān)控數(shù)據(jù)寫入臨時表中test_serverresourcetemp_lty result=a.Write_to_Mysql_temp(str) if(float(str[4])>90orfloat(str[5])>90orfloat(str[6])>85orfloat(str[7])>85orfloat(str[8])>3000orfloat(str[9])>3000): result1=a.Write_to_Mysql_alarm(str) #result=1 ifresult==0: log.logger.info('預(yù)警信息入庫失敗!') else: log.logger.info('預(yù)警信息入庫完成!') #發(fā)送預(yù)警郵件、企業(yè)微信 #a.buildMsg(str) ifdata=='exit': log.logger.info('...connecteend...') Flag=False if__name__=="__main__": #每分鐘執(zhí)行一次 log=Logger('socketservice.logs') log.logger.info('----start----') alarmName='服務(wù)器資源預(yù)警' #是否開啟郵件報警,1為開啟,0為關(guān)閉 mailconf=1 #是否開啟企業(yè)微信報警,1為開啟,0為關(guān)閉 wxconf=0 server=SocketServer.ThreadingTCPServer(('IP',port),MyServer) server.serve_forever()
客戶端腳本:
#-*-coding:utf-8-*- importio importos importsys importtime importdatetime importsocket importcommands importlogging fromloggingimporthandlers importpsutil importstruct importfcntl ifsys.getdefaultencoding()!='utf-8': reload(sys) sys.setdefaultencoding('utf-8') classLogger(object): level_relations={ 'debug':logging.DEBUG, 'info':logging.INFO, 'warning':logging.WARNING, 'error':logging.ERROR, 'crit':logging.CRITICAL }#日志級別關(guān)系映射 def__init__(self,logname,level='info',when='D',backCount=10,fmt='%(asctime)s-%(pathname)s[line:%(lineno)d]-%(levelname)s:%(message)s'): CURRENT_DIR=os.path.dirname(__file__) LOG_FILE=os.path.abspath(os.path.join(CURRENT_DIR,logname)) self.logger=logging.getLogger(LOG_FILE) format_str=logging.Formatter(fmt)#設(shè)置日志格式 self.logger.setLevel(self.level_relations.get(level))#設(shè)置日志級別 sh=logging.StreamHandler()#往屏幕上輸出 sh.setFormatter(format_str)#設(shè)置屏幕上顯示的格式 th=handlers.TimedRotatingFileHandler( filename=LOG_FILE,when=when,backupCount=backCount,encoding='utf-8')#往文件里寫入#指定間隔時間自動生成文件的處理器 #實例化TimedRotatingFileHandler #interval是時間間隔,backupCount是備份文件的個數(shù),如果超過這個個數(shù),就會自動刪除,when是間隔的時間單位,單位有以下幾種: #S秒 #M分 #H小時、 #D天、 #W每星期(interval==0時代表星期一) #midnight每天凌晨 th.setFormatter(format_str)#設(shè)置文件里寫入的格式 #self.logger.addHandler(sh)#把對象加到logger里 ifnotself.logger.handlers: self.logger.addHandler(th) classclientMonitor(object): #獲取指定網(wǎng)卡ip defgetIpAddress(self,dev): s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) a=s.fileno() b=0x8915 c=struct.pack('256s',dev[:15]) res=fcntl.ioctl(a,b,c)[20:24] returnsocket.inet_ntoa(res) #獲取網(wǎng)絡(luò)的使用情況,取的是eth0的發(fā)送和收取的總字節(jié)數(shù) #readNetInfo('eth0') defreadNetInfo(self,dev): f=open('/proc/net/dev') lines=f.readlines() f.close() res={'in':0,'out':0} forlineinlines: ifline.lstrip().startswith(dev): #forcentos line=line.replace(':','') items=line.split() res['in']=long(items[1])#/1024 res['out']=long(items[len(items)/2+1])#/1024 returnres defreadNetInfo_new(self,dev): res={'in':0,'out':0} res['in']=psutil.net_io_counters(pernic=True).get(dev).bytes_recv res['out']=psutil.net_io_counters(pernic=True).get(dev).bytes_sent returnres #磁盤使用率,path:磁盤路徑 defdisk_stat(self,path): hd={} disk=os.statvfs(path) percent=(disk.f_blocks-disk.f_bfree)*100/(disk.f_blocks-disk.f_bfree+disk.f_bavail)+1 returnpercent defnet_loop(self,dev): #end={'in':0,'out':0} res=self.readNetInfo_new(dev) #推遲執(zhí)行的秒數(shù) time.sleep(2) #new_recv,new_send=get_net_data() new_res=self.readNetInfo_new(dev) recv_data=(new_res['in']-res['in'])/1024/1024 send_data=(new_res['out']-res['out'])/1024/1024 print("recv_data:%sM,send_data:%sM"%(recv_data,send_data)) returnrecv_data,send_data defprocesscheck(self,cmd): #cmd='ps-aux|sort-k3nr|head-1' (status,output)=commands.getstatusoutput(cmd) #Pid=output.split('')[6] log.logger.info('資源占用top: '+output) #查看占用內(nèi)存最高的進(jìn)程的PID #psaux|head-1;psaux|grep-vPID|sort-rn-k+4|head #ps-aux|sort-k4nr|head-1,-k3cpu占用最高,-k4內(nèi)存占用最高 #root146681.90.0905043256?Ss4月232811:48/sbin/rngd-f #索引:-k3 b.split('')[6] 28進(jìn)程路徑(/sbin/rngd) #索引:-k4 b.split('')[4] if__name__=="__main__": #10分鐘執(zhí)行一次,數(shù)據(jù)上報到服務(wù)端,服務(wù)端負(fù)責(zé)報警 #需要修改的參數(shù):custom,deviceType,netName custom='test' deviceType='客戶端服務(wù)器' #網(wǎng)卡名稱 netName='ens3f0' log=Logger('socketclient.logs') log.logger.info("----start----") info=clientMonitor() locatIp=info.getIpAddress(netName) recv_data,send_data=info.net_loop(netName) cpuinfo=psutil.cpu_percent(1) #svmem(total=67268558848,available=32022245376,percent=52.4,used=34601009152,free=29655695360,active=17274105856,inactive=2927910912,buffers=10100736,cached=3001753600,shared=298610688,slab=11243315200) svmem=psutil.virtual_memory() meminfo=svmem[2] disk_root=info.disk_stat('/') disk_appslog=info.disk_stat('/appslog') disk_bigdata=info.disk_stat('/bigdata') #如果CPU或內(nèi)存的占用率大于80%,將占用CPU或內(nèi)存資源最多的進(jìn)程找出來 issendmsg=1 if(cpuinfo>80ormeminfo>80ordisk_root>80ordisk_appslog>80ordisk_bigdata>80orrecv_data>3000orsend_data>3000): #發(fā)送預(yù)警郵件 sendmsg=locatIp+'服務(wù)器資源占用高!請檢查! ' sendmsg+="CPU占用:"+str(cpuinfo)+' ' sendmsg+="內(nèi)存占用:"+str(meminfo)+' ' sendmsg+="/目錄占用:"+str(disk_root)+' ' sendmsg+="/appslog目錄占用:"+str(disk_appslog)+' ' sendmsg+="/bigdata目錄占用:"+str(disk_bigdata)+' ' sendmsg+="網(wǎng)卡接收流量:"+str(recv_data)+'M,發(fā)送流量'+str(send_data)+'M ' #sendmsg +="網(wǎng)卡10秒發(fā)送流量:"+str(send_data)+' ' log.logger.info(sendmsg) ifcpuinfo>80: info.processcheck('ps-aux|sort-k3nr|head-10') ifmeminfo>80: info.processcheck('ps-aux|sort-k4nr|head-10') issendmsg=1 else: #log.logger.info(locatIp+"正常") log.logger.info("CPU使用率:"+str(cpuinfo)) log.logger.info("內(nèi)存使用率:"+str(meminfo)) log.logger.info("/目錄使用率:"+str(disk_root)) log.logger.info("/appslog使用率:"+str(disk_appslog)) log.logger.info("/bigdata使用率:"+str(disk_bigdata)) log.logger.info("網(wǎng)卡接收和發(fā)送情況:接收"+str(recv_data)+"M,發(fā)送"+str(send_data)+"M") #Id,custom,deviceType,IP,cpu,mem,disk_root,disk_appslog,disk_bigdata,networkRecv,networkSend,uploadTime,temp2,temp3,temp4 msg='1'+'|'+custom+'|'+deviceType+'|'+locatIp+'|'+str(cpuinfo)+'|'+str(meminfo)+'|'+str(disk_root)+'|'+str(disk_appslog)+'|'+str(disk_bigdata)+'|'+str(recv_data)+'|'+str(send_data)+'|'+time.strftime("%Y-%m-%d%H:%M:%S",time.localtime()) ifissendmsg==1: ip_port=('IP',port) sk=socket.socket() sk.connect(ip_port) sk.sendall(msg) data=sk.recv(1024) ifdata=='1': log.logger.info("本地預(yù)警信息傳輸成功!") else: log.logger.info("本地預(yù)警信息傳輸失敗!") sk.sendall('exit') sk.close()
服務(wù)端和客戶端部署好后,執(zhí)行腳本過程中如遇到缺少 psutil 依賴包的話,則需要進(jìn)行安裝。
因為我這有準(zhǔn)備好的 psutil_rpm 包,可執(zhí)行命令:rpm -ivh python2-psutil-5.6.7-1.el7.x86_64.rpm
psutil_rpm 包獲取方式:
鏈接:https://pan.baidu.com/s/19iMY8b9nVITtgBq8F3Um_A
提取碼:PsRm
寫個定時任務(wù),以每 2 小時執(zhí)行一次該腳本。
crontab-e 0*/2***cd/opt/jiaoben;pythontest_socket_resourcemonitor.py
客戶端打印日志效果:
tail-200fsocketclient.logs
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9293瀏覽量
85850 -
ip地址
+關(guān)注
關(guān)注
0文章
303瀏覽量
17094 -
編程語言
+關(guān)注
關(guān)注
10文章
1949瀏覽量
34895 -
python
+關(guān)注
關(guān)注
56文章
4807瀏覽量
84939 -
腳本
+關(guān)注
關(guān)注
1文章
391瀏覽量
14916
原文標(biāo)題:太強(qiáng)了!利用 Python 寫了一個監(jiān)控服務(wù)器資源利用率的腳本!
文章出處:【微信號:釋然IT雜談,微信公眾號:釋然IT雜談】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論