使用python調去zabbix數據庫groups,hosts_groups,hosts,items,trends,trends_uint表格中的數據組個而成的字典形式,並將其寫入excel表格中。python
其實,核心思想就是用了下面這5個sql語句,獲取的數據以字典,列表,元組的格式進行組合,最後造成的返回格式: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,一點點找吧服務器
大致思路是抄襲別人的,可是後續在此基礎上進行了修改,站在巨人的肩膀上。app
zabbix用的是zabbix3.2,同事願意用新的東西,沒辦法,就升級了咯,這段代碼只提供大致思路,不能保證能在其餘環境下運行,此次寫的不太成功,移植性太差,看看就好了。ide
代碼部分
函數
#! /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測試