zabbix 线路质量监控自定义python模块,集成ICMPTCPUDP探测,批量监控线路质量自定义阈值联动mtr保存线路故障日志并发送至noc邮箱

互联网故障一般表现为丢包和时延增大,持续性故障不难排查,难的是间歇性或凌晨故障,后者往往来不及等我们测试就已经恢复正常,得不到异常时的mtr无法判断故障点在哪里
故此有了根据丢包率和时延变换联动mtr的需求
前段时间使用Mysql实现了这个功能,缺点是占用太多系统资源,且脚本繁重,优点是数据可复用,做多种形式的展示
后续使用socket+deque实现低能耗与轻量,也可用通过开放互联网API来做分布式监控,缺点是历史数据不留存,用完即丢
系统环境
Ubuntu 18.04.5 LTS+Python 3.6.9 
python库
自带基本库,考虑到系统权限问题没有使用第三方库
ip查询
http://ip-api.com,免费版,限制频率45次/分钟,国外归属地准确率较高,国内查询一塌糊涂,国内推荐使用ipip
1 #!/usr/bin/env python32 #-*-coding:utf-8-*-3 from collections import deque4 import itertools,time5 import queue,json6 import argparse,sys,re,os,subprocess7 import time,socket,random,string8 import threading9 from functools import reduce 10 import logging 1112 ipqli=deque() 13 filename = os.path.realpath(sys.argv[0]) 14 def logger(): 15dir = os.path.dirname(os.path.realpath(sys.argv[0])) 16log_name = dir+'/log' 17logger = logging.getLogger() 18fh = logging.FileHandler(log_name) 19formater = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s") 20fh.setFormatter(formater) 21logger.setLevel(logging.DEBUG) 22logger.addHandler(fh) 23return logger 24 log = logger() 25 #ping程序,避免系统权限问题未使用ping3 26 class Ping: 27def __init__(self,ip,count=20,udp_length=64): 28ip = tuple(ip) 29self.sip,self.tip,self.type,self.port,self.inver=ip 30self.type = self.type.lower() 31self.port = int(self.port) 32self.count=count 33self.inver = float(self.inver) 34self.udp_length=udp_length 35restime_name = 'restime_deque'+''.join(ip).replace('.','') 36pkloss_name = 'pkloss_deque'+''.join(ip).replace('.','') 37ipqevent = 'event'+''.join(ip).replace('.','') 38locals()[restime_name] = deque(maxlen=60) 39locals()[pkloss_name] = deque(maxlen=60) 40self.restime_deque = locals()[restime_name] 41self.pkloss_deque = locals()[pkloss_name] 42self.ret_restime_deque = globals()[restime_name] 43self.ret_pkloss_deque = globals()[pkloss_name] 44self.ipqevent = globals()[ipqevent] 45self.compile= r'(?<=time=)\d+\.?\d+(?= ms)' 46def _tcp(self): 47s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 48s.settimeout(1) 49start_time = time.time() 50res_count=0 51try: 52s.bind((self.sip,0)) 53s.connect((self.tip, self.port)) 54s.shutdown(socket.SHUT_RD) 55value = https://tazarkount.com/read/(time.time() - start_time)*100056self.restime_deque.append(value) 57self.pkloss_deque.append(0) 58res_count=1 59except (socket.timeout,ConnectionError): 60self.restime_deque.append(0) 61self.pkloss_deque.append(1) 62except OSError as e: 63log.debug(e) 64return 0,0 65usetime = time.time()-start_time 66sleep_time = self.inver - usetime if usetime 79self.restime_deque.append(value) 80self.pkloss_deque.append(0) 81res_count=1 82except socket.timeout: 83self.restime_deque.append(0) 84self.pkloss_deque.append(1) 85except OSError as e: 86log.debug(e) 87return 0,0 88usetime = time.time()-start_time 89sleep_time = self.inver - usetime if usetime<self.inver else self.inver 90return sleep_time,res_count 91def _icmp(self): 92res_count=0 93start_time = time.time() 94cmd = 'ping -i %s -c 1 -W 1 -I %s %s'%(self.inver,self.sip,self.tip) 95ret = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0].decode('utf8') 96try: 97value=https://tazarkount.com/read/re.findall(self.compile, ret,re.S)[0] 98self.restime_deque.append(value) 99self.pkloss_deque.append(0)100res_count=1101except:102self.pkloss_deque.append(1)103self.restime_deque.append(0)104usetime = time.time()-start_time105sleep_time = self.inver - usetime if usetimemtr.py
1 #!/usr/bin/env python3 2 #-*-coding:utf-8-*- 3 import sys,logging,os,subprocess,requests 4 import email 5 import smtplib 6 from email.header import Header 7 from email.utils import formataddr 8 from email.mime.text import MIMEText 9 def logger(ip,log_name):10logger = logging.getLogger()11fh = logging.FileHandler(log_name)12formater = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")13fh.setFormatter(formater)14logger.setLevel(logging.DEBUG)15logger.addHandler(fh)16return logger17 def ip_search(ip):18r=requests.get('http://ip-api.com/json/%s?lang=zh-CN'%ip)19ret = r.json()20return (ret['regionName']+' '+ret['city'])21 class sendemail:22def __init__(self,email_list,content,subject):23self.email_list = email_list24self.content = content25self.subject = subject26def sendemail(self):27msg = MIMEText(self.content,'plain','utf-8')28msg['from'] = formataddr(['dark','976584601@qq.com'])29msg['to'] = ','.join(self.email_list)30msg['subject'] = self.subject31service = smtplib.SMTP('smtp.qq.com')32service.login('976584601@qq.com','password')33service.sendmail('976584601@qq.com',self.email_list,msg.as_string())34service.quit()35 def mtr(ip,log_name):36mtr_log_dir = os.path.dirname(os.path.realpath(sys.argv[0]))+'/mtr_log'37cmd ='mtr -r -n -c 1 -w -b %s'%ip38data = https://tazarkount.com/read/subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0].decode('utf8')39if log_name.split('/')[-1] not in os.listdir(mtr_log_dir):40ip_city = ip_search(ip)41title = '德国腾讯到 %s %s 线路异常'%(ip_city,ip)42mail_list = ['cs11241991@163.com']43mail = sendemail(mail_list,data,title)44mail.sendemail()45log = logger(ip,log_name)46log.debug(data)47 if __name__ =='__main__':48ip = sys.argv[1]49log_name = sys.argv[2]50mtr(ip,log_name) udp探测需要服务器端开启对应端口
1 #!/usr/bin env python32 import socket3 while True:4sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)5sock.bind(('ipaddress',port))6data,addr = sock.recvfrom(65535)7sock.sendto(data,addr) 也可以使用socat,实际测试使用socat会引入额外开销,时延不准确
socat -v UDP-LISTEN:4000,fork PIPE效果

zabbix 线路质量监控自定义python模块,集成ICMPTCPUDP探测,批量监控线路质量自定义阈值联动mtr保存线路故障日志并发送至noc邮箱

文章插图
 
zabbix 线路质量监控自定义python模块,集成ICMPTCPUDP探测,批量监控线路质量自定义阈值联动mtr保存线路故障日志并发送至noc邮箱

文章插图
Mysql 版
【zabbix 线路质量监控自定义python模块,集成ICMPTCPUDP探测,批量监控线路质量自定义阈值联动mtr保存线路故障日志并发送至noc邮箱】https://www.cnblogs.com/darkchen/p/14744242.html
以驱魔为理想,为生计而奔波