使用python调去zabbix数据库groups,hosts_groups,hosts,items,trends,trends_uint表格中的数据组个而成的字典形式,并将其写入excel表格中。

其实,核心思想就是用了下面这5个sql语句,获取的数据以字典,列表,元组的格式进行组合,最后形成的返回格式:

{u'10.1.12.33': {'vfs.fs.size[/,total]': '188.65', 'vm.memory.size[total]': '7.69', 'system.swap.size[,total]': '8.00', 'net.if.out[eth0]': '69.96', 'system.cpu.util[,idle]': '99.72', 'net.if.in[eth0]': '65.26', 'system.swap.size[,free]': '8.00', 'vfs.fs.size[/,free]': '177.47', 'vm.memory.size[used]': '1.30', 'system.cpu.load[percpu,avg5]': '0.08', 'vm.memory.size[available]': '6.90'}}
sql = "select groupid from groups where name='%s'" % groupname
sql = "select hostid from hosts_groups where groupid='%s'" % groupid
sql = "select host from hosts where status=0 and flags=0 and hostid = %s" % hostid
sql = "select itemid from items where hostid='%s' and key_='%s'" % (hostid, itemname)
sql = "select avg(value_%s)/%s result from %s where itemid=%s and clock<=%d and clock>=%d" % (value, ratio, table, itemid, startime, stoptime)

将关注超过阀值的ip的cpu、内存、磁盘单独放在一个sheet中,以邮件的形式定期发送到邮箱。

目前只是实现了各种功能,但是代码还很是粗糙,有些重复冗余的函数,尤其是生成excel和阀值计算这块,后续会继续改进,同时也存在很多bug,一点点找吧

zabbix拿到数据图表显示没数据 zabbix报表导出_数据库

大体思路是抄袭别人的,但是后续在此基础上进行了修改,站在巨人的肩膀上。

zabbix拿到数据图表显示没数据 zabbix报表导出_运维_02

zabbix用的是zabbix3.2,同事愿意用新的东西,没办法,就升级了咯,这段代码只提供大体思路,不能保证能在其他环境下运行,这次写的不太成功,移植性太差,看看就行了

zabbix拿到数据图表显示没数据 zabbix报表导出_sql_03

zabbix拿到数据图表显示没数据 zabbix报表导出_zabbix拿到数据图表显示没数据_04

zabbix拿到数据图表显示没数据 zabbix报表导出_python_05

zabbix拿到数据图表显示没数据 zabbix报表导出_zabbix拿到数据图表显示没数据_06

zabbix拿到数据图表显示没数据 zabbix报表导出_python_07

zabbix拿到数据图表显示没数据 zabbix报表导出_python_08


代码部分

#! /usr/bin/env python
# _*_ coding: utf-8 _*_
# Author:wangpengtai
# date:2017/7/10
import sys
import time, datetime
import MySQLdb.cursors
import xlsxwriter
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
reload(sys)
sys.setdefaultencoding('utf-8')
zbx_host = '10.1.xxx.xxx'
zbx_port = 3306
zbx_username = 'zabbix'
zbx_password = 'xxxx'
zbx_dbname = 'zabbix'
#需要查询的服务器所在组名
groupname = 'xxx_xxx_Linux_Servers'
#文件产生日期
date = time.strftime("%Y%m%d", time.localtime())
#文件名称
fname = 'Zabbix_Report_weekly_%s.xls' % date
# groupname = 'Templates'
keys = [
    [u'CPU平均空闲值', 'trends', 'system.cpu.util[,idle]', 'avg', '%.2f', 1, ''],
    [u'CPU最小空闲值', 'trends', 'system.cpu.util[,idle]', 'min', '%.2f', 1, ''],
    [u'CPU5分钟负载', 'trends', 'system.cpu.load[percpu,avg5]', 'avg', '%.2f', 1, ''],
    [u'物理内存大小(单位G)', 'trends_uint', 'vm.memory.size[total]', 'avg', '', 1073741824, 'G'],
    [u'物理内存可用(单位G)', 'trends_uint', 'vm.memory.size[available]', 'avg', '', 1073741824, 'G'],
    [u'物理内存已使用(单位G)', 'trends_uint', 'vm.memory.size[used]', 'avg', '', 1073741824, 'G'],
    [u'swap总大小(单位G)', 'trends_uint', 'system.swap.size[,total]', 'avg', '', 1073741824, 'G'],
    [u'swap平均剩余(单位G)', 'trends_uint', 'system.swap.size[,free]', 'avg', '', 1073741824, 'G'],
    [u'根分区总大小(单位G)', 'trends_uint', 'vfs.fs.size[/,total]', 'avg', '', 1073741824, 'G'],
    [u'根分区剩余(单位G)', 'trends_uint', 'vfs.fs.size[/,free]', 'avg', '', 1073741824, 'G'],
    [u'网卡进口流量(单位Kbps)', 'trends_uint', 'net.if.in[eth0]', 'avg', '', 1024, 'Kbps'],
    [u'网卡进口流量(单位Kbps)', 'trends_uint', 'net.if.in[em1]', 'avg', '', 1024, 'Kbps'],
    [u'网卡出口流量(单位Kbps)', 'trends_uint', 'net.if.out[eth0]', 'avg', '', 1024, 'Kbps'],
    [u'网卡出口流量(单位Kbps)', 'trends_uint', 'net.if.out[em1]', 'avg', '', 1024, 'Kbps'],
]
Title = [
    u'CPU5分钟负载',
    u'CPU平均空闲值',
    u'CPU最小空闲值',
    u'swap平均剩余(单位G)',
    u'swap总大小(单位G)',
    u'根分区剩余(单位G)',
    u'根分区总大小(单位G)',
    u'物理内存可用(单位G)',
    u'物理内存大小(单位G)',
    u'物理内存已使用(单位G)',
    u'网卡出口流量(单位Kbps)',
    u'网卡进口流量(单位Kbps)',
    u'硬盘剩余率(单位%)',
    u'Swap剩余率(单位%)',
    u'内存使用率(单位%)'
]
Title_dict = {
    u'CPU5分钟负载': 1,
    u'CPU平均空闲值': 2,
    u'CPU最小空闲值': 3,
    u'swap平均剩余(单位G)': 4,
    u'swap总大小(单位G)': 5,
    u'根分区剩余(单位G)': 6,
    u'根分区总大小(单位G)': 7,
    u'物理内存可用(单位G)': 8,
    u'物理内存大小(单位G)': 9,
    u'物理内存已使用(单位G)': 10,
    u'网卡出口流量(单位Kbps)': 11,
    u'网卡进口流量(单位Kbps)': 12,
    u'硬盘剩余率(单位%)': 13,
    u'Swap剩余率(单位%)': 14,
    u'内存使用率(单位%)': 15
}
disk_full = Title[6]
disk_free = Title[5]
swap_full = Title[4]
swap_free = Title[3]
mem_full = Title[8]
mem_used = Title[9]
keys_disk = Title[12]
keys_swap = Title[13]
keys_mem = Title[14]
keys_cpu= Title[0]
class Report(object):
    def __init__(self):
        self.conn = MySQLdb.connect(host=zbx_host, port=zbx_port, user=zbx_username, passwd=zbx_password, db=zbx_dbname,
                               charset="utf8", cursorclass=MySQLdb.cursors.DictCursor)
        self.cursor = self.conn.cursor()
    def getgroupid(self):
        sql = "select groupid from groups where name='%s'" % groupname
        self.cursor.execute(sql)
        groupid = self.cursor.fetchone()['groupid']
        # print 'groupid is %s' % groupid
        return groupid
    def gethostid(self):
        # sql = '''select hostid from hosts_groups where groupid=(select groupid from groups where name='%s') ''' %groupname
        groupid = self.getgroupid()
        # print groupid
        sql = "select hostid from hosts_groups where groupid='%s'" % groupid
        self.cursor.execute(sql)
        hostid_list = self.cursor.fetchall()
        # print 'hostid_list:',hostid_list
        return hostid_list
        # 元组格式:({'hostid': 10322L}, {'hostid': 10323L}, {'hostid': 10324L})
    def gethostlist(self):
        host_list = {}
        hostid_list = self.gethostid()
        # print hostid_list
        for item in hostid_list:
            # print item
            hostid = item['hostid']
            # print hostid
            sql = "select host from hosts where status=0 and flags=0 and hostid = %s" % hostid
            self.cursor.execute(sql)
            host_ip = self.cursor.fetchone()
            # print host_ip
            # print host_ip['host']
            #!!!判断如果主机被zabbix改成disable的状态时,hosts表格里面host变为空后,字典空键赋值报错《TypeError: 'NoneType' object has no attribute '__getitem__'》
            if host_ip is None:
                continue
            host_list[host_ip['host']] = {'hostid': hostid}
        # print host_list
        return host_list
        # 字典格式:{u'10.1.12.32': {'hostid': 10175L}, u'10.1.12.33': {'hostid': 10176L}}
    def getitemid(self):
        hostid_list = self.gethostlist()
        # print hostid_list.items()
        keys_dict = {}
        for hostitem in hostid_list.items():
            hostip = hostitem[0]
            hostid = hostitem[1]['hostid']
            # print hostitem
            host_info = []
            for item in keys:
                keys_list = []
                keys_list.append({'title': item[0]})
                keys_list.append({'table': item[1]})
                keys_list.append({'itemname': item[2]})
                keys_list.append({'value': item[3]})
                keys_list.append({'form': item[4]})
                keys_list.append({'ratio': item[5]})
                keys_list.append({'unit': item[6]})
                itemname = item[2]
                sql = "select itemid from items where hostid='%s' and key_='%s'" % (hostid, itemname)
                self.cursor.execute(sql)
                itemid = self.cursor.fetchone()
                if itemid is None:
                    continue
                keys_list.append(itemid)
                # keys_dict['itemid'] = itemid['itemid']
                # print hostip,keys_dict
                host_info.append(tuple(keys_list))
                # print host_info
            keys_dict[hostip] = host_info
        # print keys_dict
        return keys_dict
    def getvalue(self):
        # 时间区间为7天内
        stoptime = time.time() - 7*3600
        startime = time.time()
        host_info_list = self.getitemid()
        # print host_info_list
        host_dict = {}
        for ip in host_info_list:
            host_info = host_info_list[ip]
            length = len(host_info)
            host_item = {}
            for i in range(length):
                value = host_info[i][3]['value']
                ratio = host_info[i][5]['ratio']
                table = host_info[i][1]['table']
                itemid = host_info[i][7]['itemid']
                # itemname = host_info[i][2]['itemname']
                unit = host_info[i][6]['unit']
                title = host_info[i][0]['title']
                sql = "select avg(value_%s)/%s result from %s where itemid=%s and clock<=%d and clock>=%d" % (
                    value, ratio, table, itemid, startime, stoptime)
                self.cursor.execute(sql)
                result = self.cursor.fetchone()['result']
                if result is None:
                    continue
                else:
                    host_item[title] = '%.2f%s' % (result, unit)
            # 硬盘剩余率
            if disk_full in host_item and disk_free in host_item:
                # print "Disk_percent:%.2f%%" %(float(host_item[disk_free].strip("GKbps"))/float(host_item[disk_full].strip("GKbps"))*100)
                host_item[keys_disk] = "%.2f" % (
                    float(host_item[disk_free].strip("GKbps")) / float(host_item[disk_full].strip("GKbps")) * 100)
            # Swap剩余率
            if swap_full in host_item and swap_free in host_item:
                # print "Swap_percent:%.2f%%" %(float(host_item[swap_full].strip("GKbps"))/float(host_item[swap_full].strip("GKbps"))*100)
                host_item[keys_swap] = "%.2f" % (
                    float(host_item[swap_full].strip("GKbps")) / float(host_item[swap_full].strip("GKbps")) * 100)
            # 内存使用率
            if mem_used in host_item and mem_full in host_item:
                # print "Mem_percent:%.2f%%" %(float(host_item[mem_used].strip("GKbps")) / float(host_item[mem_full].strip("GKbps")) * 100)
                host_item[keys_mem] = "%.2f" % (
                    float(host_item[mem_used].strip("GKbps")) / float(host_item[mem_full].strip("GKbps")) * 100)
            host_dict[ip] = host_item
        return host_dict
        # 返回格式:{u'10.1.12.33': {'vfs.fs.size[/,total]': '188.65', 'vm.memory.size[total]': '7.69', 'system.swap.size[,total]': '8.00', 'net.if.out[eth0]': '69.96', 'system.cpu.util[,idle]': '99.72', 'net.if.in[eth0]': '65.26', 'system.swap.size[,free]': '8.00', 'vfs.fs.size[/,free]': '177.47', 'vm.memory.size[used]': '1.30', 'system.cpu.load[percpu,avg5]': '0.08', 'vm.memory.size[available]': '6.90'}}
    def dispalyvalue(self):
        value = self.getvalue()
        for ip in value:
            print "\n\rip:%s\n\r获取服务器信息:" % (ip)
            for key in value[ip]:
                print "%s:%s" %(key,value[ip][key])
    def __del__(self):
        #关闭数据库连接
        self.cursor.close()
        self.conn.close()
    def createreport(self):
        host_info = self.getvalue()
        # 创建一个excel表格
        workbook = xlsxwriter.Workbook(fname)
        # 设置第一行标题格式
        format_title = workbook.add_format()
        format_title.set_border(1)  # 边框
        format_title.set_bg_color('#1ac6c0')  # 背景颜色
        format_title.set_align('center')  # 左右居中
        format_title.set_bold()  # 字体加粗
        format_title.set_valign('vcenter')  # 上下居中
        format_title.set_font_size(12)
        # 设置返回值的格式
        format_value = workbook.add_format()
        format_value.set_border(1)
        format_value.set_align('center')
        format_value.set_valign('vcenter')
        format_value.set_font_size(12)
        # 创建一个名为Report的工作表
        worksheet1 = workbook.add_worksheet("总览表格")
        # 设置列宽
        worksheet1.set_column('A:D', 15)
        worksheet1.set_column('E:J', 23)
        worksheet1.set_column('K:P', 25)
        # 设置行高
        worksheet1.set_default_row(25)
        # 冻结首行首列
        worksheet1.freeze_panes(1, 1)
        # 将标题写入第一行
        i = 1
        for title in Title:
            worksheet1.write(0, i, title.decode('utf-8'), format_title)
            i += 1
        # 写入第一列、第一行
        worksheet1.write(0, 0, "主机".decode('utf-8'), format_title)
        # 根据每个ip写入相应的数值
        j = 1
        for ip in host_info:
            keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
            host_value = host_info[ip]  # 取出没有排序的键值
            if len(host_value) != 0:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                worksheet1.write(j, 0, ip, format_value)
            else:
                continue
            # k = 1
            for item in keys_ip:
                # worksheet1.write(j,k,host_value[item],format_value)
                worksheet1.write(j, Title_dict[item], host_value[item], format_value)
                # k += 1
            j += 1
##########################性能报表#############################
        worksheet2 = workbook.add_worksheet("性能报表")
        # 设置列宽
        worksheet2.set_column('A:E', 25)
        # 设置行高
        worksheet2.set_default_row(25)
        # 冻结首行首列
        worksheet2.freeze_panes(1, 1)
        # 写入第一列、第一行
        worksheet2.write(0, 0, "主机".decode('utf-8'), format_title)
        worksheet2.write(0, 1, keys_cpu, format_title)
        worksheet2.write(0, 2, keys_mem, format_title)
        worksheet2.write(0, 3, keys_swap, format_title)
        worksheet2.write(0, 4, keys_disk, format_title)
        j = 1
        for ip in host_info:
            keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
            host_value = host_info[ip]  # 取出没有排序的键值
            #Title[12]=硬盘剩余率(单位%)
            if len(host_value) != 0 and keys_disk in host_value and keys_swap in host_value and keys_mem in host_value and keys_cpu in host_value:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                worksheet2.write(j, 0, ip, format_value)
                worksheet2.write(j, 1, host_value[keys_cpu], format_value)
                worksheet2.write(j, 2, host_value[keys_mem], format_value)
                worksheet2.write(j, 3, host_value[keys_swap], format_value)
                worksheet2.write(j, 4, host_value[keys_disk], format_value)
    #keys_mem in host_value: # or keys_swap in host_value
            else:
                continue
            j += 1
###############制作内存大于90%的服务器表格########################
        worksheet3 = workbook.add_worksheet("内存大于90%")
        # 设置列宽
        worksheet3.set_column('A:B', 25)
        # 设置行高
        worksheet3.set_default_row(25)
        # 冻结首行首列
        worksheet3.freeze_panes(1, 1)
        # 写入第一列、第一行
        worksheet3.write(0, 0, "主机".decode('utf-8'), format_title)
        worksheet3.write(0, 1, keys_mem, format_title)
        j = 1
        for ip in host_info:
            keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
            host_value = host_info[ip]  # 取出没有排序的键值
            if len(host_value) != 0 and keys_mem in host_value and float(host_value[keys_mem]) > 90.0:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                #print type(float(host_value[keys_mem]))
                #if float(host_value[keys_mem]) < 20.0:
                worksheet3.write(j, 0, ip, format_value)
                worksheet3.write(j, 1, host_value[keys_mem], format_value)
            else:
                continue
            j += 1
#######################制作硬盘空间小于20%的服务器表格#########################
        # 制作硬盘空间小于20%的服务器表格
        worksheet4 = workbook.add_worksheet("磁盘空间低于20%")
        # 设置列宽
        worksheet4.set_column('A:B', 25)
        # 设置行高
        worksheet4.set_default_row(25)
        # 冻结首行首列
        worksheet4.freeze_panes(1, 1)
        # 写入第一列、第一行
        worksheet4.write(0, 0, "主机".decode('utf-8'), format_title)
        worksheet4.write(0, 1, keys_disk, format_title)
        j = 1
        for ip in host_info:
            keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
            host_value = host_info[ip]  # 取出没有排序的键值)
            if len(host_value) != 0 and keys_disk in host_value and float(
                    host_value[keys_disk]) < 20.0:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                # print type(float(host_value[keys_disk]))
                # if float(host_value[keys_disk]) < 20.0:
                worksheet4.write(j, 0, ip, format_value)
                worksheet4.write(j, 1, host_value[keys_disk], format_value)
            else:
                continue
            j += 1
            
#######################制作CPU负载大于8的服务器表格#########################
            # 制作CPU负载大于8的服务器表格
            worksheet5 = workbook.add_worksheet("CPU负载大于8")
            # 设置列宽
            worksheet5.set_column('A:B', 25)
            # 设置行高
            worksheet5.set_default_row(25)
            # 冻结首行首列
            worksheet5.freeze_panes(1, 1)
            # 写入第一列、第一行
            worksheet5.write(0, 0, "主机".decode('utf-8'), format_title)
            worksheet5.write(0, 1, keys_cpu, format_title)
            j = 1
            for ip in host_info:
                keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
                host_value = host_info[ip]  # 取出没有排序的键值
                if len(host_value) != 0 and keys_cpu in host_value and float(
                        host_value[keys_cpu]) > 8:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                    # print type(float(host_value[keys_cpu]))
                    # if float(host_value[keys_cpu]) < 20.0:
                    worksheet5.write(j, 0, ip, format_value)
                    worksheet5.write(j, 1, host_value[keys_cpu], format_value)
                else:
                    continue
                j += 1
        workbook.close()
    def sendreport(self):
        # 发件服务器地址
        mail_host = 'smtp.163.com'
        # 发件邮箱地址
        sender_user = 'xxxx_monitor@163.com'
        # mail_pass = 'xxxx'#登录密码
        # 邮箱授权码,不是登录密码
        sender_pass = 'xxxxx'
        # 收件邮箱地址
        receivers = ['wangpengtai@xxx.com', 'wangpeng@xxx.cn']
        # 创建带附件实例
        message = MIMEMultipart()
        # 邮件内容
        # message = MIMEText('Python 邮件测试发送','plain','utf-8')
        # 发送邮箱地址
        message['From'] = sender_user
        # 群发邮件时会报错message['To']不支持列表,使用join函数把地址合成字符串
        message['To'] = ",".join(receivers)
        # 邮件主题
        subject = '一周服务器资源使用情况报表'
        message['Subject'] = subject.decode('utf-8')
        # 邮件正文内容
        message.attach(MIMEText('一周服务器资源使用情况报表', 'plain', 'utf-8'))
        # 构造附件1,传送当前目录下
        excel = MIMEApplication(open(fname, 'rb').read(), 'utf-8')
        excel.add_header('Content-Disposition', 'p_w_upload', filename=fname)
        message.attach(excel)
        try:
            smtpobj = smtplib.SMTP()
            # smtpobj.set_debuglevel(1)
            smtpobj.connect(mail_host, 25)
            smtpobj.login(sender_user, sender_pass)
            smtpobj.sendmail(sender_user, receivers, message.as_string())
            smtpobj.close()
            print '邮件发送成功'
        except:
            print "邮件发送失败"
if __name__ == "__main__":
    zabbix = Report()
    zabbix.dispalyvalue()
    zabbix.createreport()
    zabbix.sendreport()

参考大神:

http://www.roncoo.com/article/detail/126748


转载于:https://blog.51cto.com/wangpengtai/1952579