首页 > 编程语言 > 详细

zabbix python线路质量监控模块,自定义监控粒度,链路丢包或时延抖动联动mtr

时间:2021-05-08 22:50:07      阅读:30      评论:0      收藏:0      [点我收藏+]

之前零零碎碎写了一些zabbix 线路监控的脚本,工作中agnet较多,每条线路监控需求不一致,比较杂乱,现在整理成一个py模块,集合之前的所有功能

环境

  python3.6以上版本,pip3(pip 9.0.1以上版本),mysql,pymysql库

  使用zabbix自定义脚本获取线路时延丢包率不做介绍,参考上一篇zabbix文章

如果系统当前python版本是python3.5,升级3.6时有两个注意事项

  1 先升级python至3.6再升级pip3否则会导致pip3无法正常使用

  2 python3.5升级到3.6后需要把lsb_release.py 文件复制到python3.6的lib里,否则pip3无法正常使用

  3 上两步完成后再进行pip3升级

 

 

darkping包文件如下
  -----bin----程序入口,接收参数调用views
    -----views-----逻辑函数,计算并返回
      -----mtr.sh----shell脚本,供views调用
      -----start-sql----初始化数据插入
        ------tcping----使用socket计算tcp时延丢包工具
  -----log----日志文件
  -----models-----数据库相关
  -----settings----配置文件,sql语句,文件路径,重要参数等

 

bin代码

#!/usr/bin/env python3
#-*-coding:utf-8-*-
#----------------------------------------------------------zabbixping脚本----------------------------------------------------
import argparse
from views import dark_zabbix


if __name__  == "__main__":
    parser = argparse.ArgumentParser(description=icmp for monitor)
    parser.add_argument(-t,action = store,dest=tip)
    parser.add_argument(-i,action=store,dest=interval,default=1)
    parser.add_argument(-I,action=store,dest=item)
    parser.add_argument(-p,action=store,dest=port,default=0)
    parser.add_argument(-T,action = store,dest=type,default=icmp)
    args= parser.parse_args()
    ip = args.tip
    i = float(args.interval)
    item = args.item
    port = int(args.port)
    t_ype = args.type
    print(dark_zabbix(ip,item,i,port,t_ype))

 

views代码

#!/usr/bin/env python3
#-*-coding:utf-8-*-
import log,models,time,subprocess
from models import db
from settings import dbinfo
def dark_zabbix(ip,item,i,port,t_ype):
    #初始化
    res_ret = 0
    pkloss_ret = 0
    #根据频率计算所select的数据数量,20是zabbix前端获取数据的时间间隔
    packet_count= int(20/i)
    #实例化dbinfo
    dbvalues = dbinfo()
    #logger对象
    logger = log.logger()
    #获取调用pingsql命令
    cmd = dbvalues.cmd(ip,i,port,t_ype)
    #获取sql语句
    sql_statues = dbvalues.sql_sqlstatues(ip,t_ype,port)
    sql_getvalue = dbvalues.sql_getvalue(ip,packet_count,t_ype,port)
    sql_mtr = dbvalues.sql_mtr(ip,packet_count,t_ype,port)
    
    #实例化mysql对象,调用readone/all方法
    my_sql = db(dbvalues.dbinfo())
    lasttime = my_sql.db_readone(sql_statues)
    now_time = int(time.time())
    #判断最新数据时间与当前时间间隔是否超过1分钟,新建item或防止系统重启后台程序异常等
    try:
        ctime = (lasttime[time])
        if now_time - ctime > 60:
            raise Exception(dberror)
    except Exception as a:
        #调用pingsql脚本开始进行探测并写入数据库
        subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        return(res_ret)
    #根据所设置的粒度取相应的数据
    ret = my_sql.db_readall(sql_getvalue)
    if len(ret) <packet_count:
        return(res_ret)
    else:
        for x in ret:
            res_ret+=x[res]
            pkloss_ret+=x[pkloss]
    #计算时延和丢包率
    restime = (round(float(res_ret/packet_count),2))
    pkloss = (round(float(pkloss_ret/packet_count*100),2))
    #计算本次与上次时延差值与本次丢包率,决定是否调用mtr
    try:
        history_restime = round(float(my_sql.db_readone(sql_mtr)[avg(a.res)]),2)
        if restime - history_restime > 20 or 100> pkloss >20:
            mtr = dbvalues.mtr(ip)
            subprocess.Popen(mtr,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    except Exception as a:
        logger.info(a)
       
    if item ==restime:
        my_sql.db_close()
        return  restime
    if item == pkloss:
        my_sql.db_close()
        return  pkloss

 

start-sql代码

#!/usr/bin/env python3
#-*-coding:utf-8-*-
import subprocess,re,time,pymysql,argparse
from settings import dbinfo
from models import db
import log

def ping(cmd):
    pkloss = 0
    ret = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0].decode(utf8)
    try:
        ret =re.findall(\d+\.?\d* ,(re.findall(time=\d+\.?\d*,ret)[0]))[0]
        return(ret,pkloss)
    except Exception as a :
        ret = 0
        pkloss = 1
        return(ret,pkloss)
def value(i,ipaddress,port,t_ype):
    if t_ype == icmp:
        cmd = ping  -c 1 -W 1 %s%ipaddress
    elif t_ype ==tcp:
        cmd = ./tcping.py %s %s 1%(ipaddress,port)
    i = float(i)
    logger = log.logger()
    logger.debug(初始化%s%ipaddress)
    
    dbvalues = dbinfo()
    mysql = db(dbvalues.dbinfo())
    while True:
start_time = time.time() res,pkloss
= ping(cmd) t_time = int(time.time()) ctime = t_time - 86400*2 #获取清空历史数据sql语句 sql = dbvalues.sql_clearhistory(ctime) sql1 = dbvalues.sql_insert(res,pkloss,ipaddress,t_time,t_ype,port)#清空48小时前数据 mysql.db_delete(sql) #写入新数据 mysql.db_write(sql1)
use_time = time.time()-start_time
#时间修正 time.sleep(i-use_time)
return if __name__ == "__main__": parser = argparse.ArgumentParser(description=icmp for monitor) parser.add_argument(-t,action = store,dest=tip) parser.add_argument(-i,action=store,dest=interval) parser.add_argument(-p,action=store,dest=port) parser.add_argument(-T,action = store,dest=type) args= parser.parse_args() ip = args.tip i = args.interval port = args.port t_ype = args.type value(i,ip,port,t_ype)

 

tcping代码

#!/usr/bin/env python3
"""
TCP Ping Test (defaults to port 80, 10000 packets)
Usage: ./tcpping.py host [port] [maxCount]
- Ctrl-C Exits with Results
"""

import sys
import socket
import time
import signal
from timeit import default_timer as timer

host = None
port = 80


maxCount = 10000
count = 0


# try:
#     sip = sys.argv[1]
# except IndexError:
#     print("Usage: tcpping.py host [port] [maxCount]")
#     sys.exit(1)

try:
    host = sys.argv[1]
except IndexError:
    print("Usage: tcpping.py host [port] [maxCount]")
    sys.exit(1)


try:
    port = int(sys.argv[2])
except ValueError:
    print("Error: Port Must be Integer:", sys.argv[3])
    sys.exit(1)
except IndexError:
    pass


try:
    maxCount = int(sys.argv[3])
except ValueError:
    print("Error: Max Count Value Must be Integer", sys.argv[3])
    sys.exit(1)
except IndexError:
    pass



passed = 0
failed = 0


def getResults():
    """ Summarize Results """

    lRate = 0
    if failed != 0:
        lRate = failed / (count) * 100
        lRate = "%.2f" % lRate

    print("\nTCP Ping Results: Connections (Total/Pass/Fail): [{:}/{:}/{:}] (Failed: {:}%)".format((count), passed, failed, str(lRate)))

def signal_handler(signal, frame):
    """ Catch Ctrl-C and Exit """
    getResults()
    sys.exit(0)


signal.signal(signal.SIGINT, signal_handler)


while count < maxCount:


    count += 1

    success = False


    s = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)


    s.settimeout(1)

    s_start = timer()


    try:
        # s.bind((sip,0))
        s.connect((host, int(port)))
        s.shutdown(socket.SHUT_RD)
        success = True
    

    except socket.timeout:
        print("Connection timed out!")
        failed += 1
    except OSError as e:
        print("OS Error:", e)
        failed += 1


    s_stop = timer()
    s_runtime = "%.2f" % (1000 * (s_stop - s_start))

    if success:
        print("Connected to %s[%s]: tcp_seq=%s time=%s ms" % (host, port, (count-1), s_runtime))
        passed += 1


    if count < maxCount:
        time.sleep(1)


getResults()

 

log代码

#!/usr/bin/env python3
#-*-coding:utf-8-*-
import logging,time
from settings import dbinfo
def logger():
    base_dir = dbinfo()
    log_name = base_dir.log_dir()
    logger = logging.getLogger()
    fh = logging.FileHandler(log_name)
    formater = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
    fh.setFormatter(formater)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(fh)
    return logger

 

models代码

#!/usr/bin/env python3
#-*-coding:utf-8-*-
#-----------------------------------------------------创建db类--------------------------------------------------------
import pymysql,settings
class db:
    def __init__(self,conninfo):
        self.host = conninfo[host]
        self.port = conninfo[port]
        self.user = conninfo[user]
        self.passwd = conninfo[passwd]
        self.db = conninfo[db]
        self.ch = conninfo[charset]
        self.conn = pymysql.connect(host=self.host,port = self.port,user = self.user,passwd = self.passwd, db=self.db,charset=self.ch)
        self.coursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
     
    def db_readone(self,sql):
        self.coursor.execute(sql)
        return self.coursor.fetchone()
    def db_readall(self,sql):
        self.coursor.execute(sql)
        return self.coursor.fetchall()
    def db_write(self,sql):
        self.coursor.execute(sql)
        self.conn.commit()
    def db_delete(self,sql):
        self.coursor.execute(sql)
        self.conn.commit()
    def db_close(self):
        self.conn.close()

 

settings代码

#!/usr/bin/env python3
#-*-coding:utf-8-*-
#---------------------------------------------配置文件,定义sql语句,路径等------------------------------------------------
import os,time

class dbinfo:
    def __init__(self):
        self.dir = os.path.dirname(os.path.abspath(__file__))
    def base_dir(self):
        return self.dir
    def log_dir(self):
        log_dir = self.dir + /log/ + time.strftime(%Y-%m-%d,time.localtime()) + .log
        return log_dir
    def mtr(self,ip):
        mtr_dir = self.dir+/log/+ip+-+time.strftime(%Y-%m-%d,time.localtime()) + .log
        cmd = self.dir + /mtr.sh+ +ip+ +mtr_dir
        return cmd
    def dbinfo(self):
        dbinfo = {host:127.0.0.1,port:3306,user:root,passwd:‘test, db:pingvalues,charset:utf8}
        return dbinfo
    def sql_sqlstatues(self,ip,t_ype,port):
        sql = select time  from zabbixvalue where ipaddress like "%s" and type like "%s"  and port like %s order by nid  desc limit 1;%(ip,t_ype,port)
        return sql
    def sql_getvalue(self,ip,packet_count,t_ype,port):
        sql = select res,pkloss,ipaddress,time  from zabbixvalue where ipaddress like "%s" and type like "%s" and port like %s order by nid  desc limit %s;%(ip,t_ype,port,packet_count)
        return sql
    def cmd(self,ip,i,port,t_ype):
        cmd = ‘nohup‘+‘ ‘+self.dir + /start-sql.py -t %s -i %s -p %s -T %s >/dev/null 2>&1 &%(ip,i,port,t_ype)
        return cmd
    def sql_clearhistory(self,ctime):
        sql = delete from zabbixvalue where time<%s;%ctime
        return sql
    def sql_insert(self,res,pkloss,ipaddress,t_time,t_ype,port):
        sql = insert into zabbixvalue(res,pkloss,ipaddress,time,type,port) values(%s,%s,"%s",%s,"%s",%s)%(res,pkloss,ipaddress,t_time,t_ype,port)
        return sql
    def sql_mtr(self,ip,packet_count,t_ype,port):
        sql = select avg(a.res) from (select res from zabbixvalue where ipaddress like "%s" and type like "%s" and port like %s order by nid  desc limit %s,%s) as a;%(ip,t_ype,port,packet_count,packet_count)
        return sql

  

mtr shell脚本

#!/usr/bin/env bash
IP=$1
dir=$2
mtr -r -n -c 30 -w -b $IP >> $2

 

mysql

mysql> desc zabbixvalue;
+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| nid       | int(11)     | NO   | PRI | NULL    | auto_increment |
| res       | float       | YES  |     | NULL    |                |
| pkloss    | int(11)     | YES  |     | NULL    |                |
| ipaddress | varchar(64) | YES  |     | NULL    |                |
| time      | int(11)     | YES  |     | NULL    |                |
| type      | varchar(64) | YES  |     | NULL    |                |
| port      | int(11)     | YES  |     | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)

zabbix_agentd.conf

UserParameter=dark_ping_restime[*],/etc/zabbix/darkping/bin.py     -t $1 -I restime
UserParameter=dark_ping_pkloss[*],/etc/zabbix/darkping/bin.py     -t $1 -I pkloss


UserParameter=dark_tcpping_restime[*],/etc/zabbix/darkping/bin.py     -t $1 -p $2 -T tcp -I restime
UserParameter=dark_tcpping_pkloss[*],/etc/zabbix/darkping/bin.py     -t $1 -p $2 -T tcp -I pkloss

Item 配置略

zabbix python线路质量监控模块,自定义监控粒度,链路丢包或时延抖动联动mtr

原文:https://www.cnblogs.com/darkchen/p/14744242.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!