监控告警系统是我们运维工作当中非常核心的一个平台。但是总会有一些特殊需求不方便完全通过告警来实现。同时当前python的应用越来越广,需求越来越多。而作为dba的我们也更应该与时俱进学习python来提升自身技能,也能帮助我们提升日常工作当中的效率。
同时,我也相信有不少DBA或者其他专业的人员都想学习当前火热到不行的python。基于此,我也是乐于把自己自学到的一些感觉有用的东西分享出来,和大家一起探讨一起进步。所以我会把我日常工作中使用到、实验到的一些脚本案例奉献给大家,组成一个专栏。
PS:我作为一个DBA然后半路出家自学python的人来说,对于python技术的理解和使用肯定是不够专业的,也请大家不吝赐教,不喜勿喷。
话不多说,MySQL数据库相关案例中,选了一个自己试验用来监控主从同步的脚本,内容如下:
#!/usr/bin/python
# Python 2.6.6
# -*- coding:utf-8 -*-
import re
import os
import smtplib
import time
import datetime
import base64
import MySQLdb
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
#定义基础信息
dbhosts = ('dbatest1-prd.test.com.cn', 'dbatest2-prd.test.com.cn', 'dbatest3-prd.test.com.cn', 'dbatest4-stg.test.com.cn')
dbuser = 'root'
dbpasswd = 'dbatest#1234'
dbport = 3306
#定义html文件头
html_header = """
<p>
<font size='5' color='RED'>
表格中如有标红部分,请立即处理,谢谢!
</font>
</p>
<table border='1'>
<tr>
<th Bgcolor=#00FFFF> HOST </th>
<th Bgcolor=#00FFFF> Slave_IO_Running </th>
<th Bgcolor=#00FFFF> Slave_SQL_Running </th>
<th Bgcolor=#00FFFF> Seconds_Behind_Master </th>
<th Bgcolor=#00FFFF> SQL_Delay </th>
</tr>
"""
#定义html文件主题信息,用列表记录
html_list = []
#函数获取slave status信息,生产html文件
def get_slave_status(dbhosts, dbuser, dbpasswd, dbport, cfile):
#清空并写入html文件头
open(cfile, 'w').write(html_header)
#循环操作列表中的数据库
for dbhost in dbhosts:
try:
#建立连接
conn = MySQLdb.connect(host=dbhost, port=dbport, user=dbuser, passwd=dbpasswd)
#定义cursor,接收字典类型的结果
cur = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor)
#执行sql
res = cur.execute('show slave status')
#获取数据
data = cur.fetchall()
#将数据的列表指定到字典里
slave_dict = data[0]
#获取对应所需的字典key和value
Slave_IO_Running = slave_dict['Slave_IO_Running']
Slave_SQL_Running = slave_dict['Slave_SQL_Running']
Seconds_Behind_Master = slave_dict['Seconds_Behind_Master']
SQL_Delay = slave_dict['SQL_Delay']
except:
Slave_IO_Running = ''
Slave_SQL_Running = ''
Seconds_Behind_Master = ''
SQL_Delay = ''
if Slave_IO_Running != 'Yes' or Slave_SQL_Running != 'Yes' or Seconds_Behind_Master > 1800 or SQL_Delay != 0:
html_info = """
<tr>
<td Bgcolor=RED> {0} </td>
<td Bgcolor=RED> {1} </td>
<td Bgcolor=RED> {2} </td>
<td Bgcolor=RED> {3} </td>
<td Bgcolor=RED> {4} </td>
</tr>
""".format(dbhost, Slave_IO_Running, Slave_SQL_Running, Seconds_Behind_Master, SQL_Delay)
#如果同步异常,则html表格字体标红,并放到列表的最前位置
html_list.insert(0, html_info)
else:
html_info = """
<tr>
<td> {0} </td>
<td> {1} </td>
<td> {2} </td>
<td> {3} </td>
<td> {4} </td>
</tr>
""".format(dbhost, Slave_IO_Running, Slave_SQL_Running, Seconds_Behind_Master, SQL_Delay)
#如果同步正常,则普通字体和颜色,追加到列表末尾。
html_list.append(html_info)
#无法直接写入列表到文件,所以需要将列表逐行写入
for i in range(len(html_list)):
html_list_info = html_list[i]
open(cfile, 'a').write(html_list_info)
open(cfile, 'a').close()
def send_mail(cfile):
#邮箱发件服务器
mail_host = "XXXXXXXXXXX"
mail_user = "XXXXXXXXX"
#定义密文,取实际的密码base64解析结果
mail_en_passwd = "XXXXXXXXX"
#解析密文为实际密码
mail_passwd = base64.b64decode(mail_en_passwd).decode()
receivers = ['XXXXXXXXXX']
me = "MySQL ALERT" + "<" + mail_user + ">"
msg = MIMEMultipart()
##邮件标题
subject = '【告警】:数据库MySQL slave status告警'
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = Header(me, 'utf-8')
# 收件人为多人时,添加收件人
msg['To'] = Header(', '.join(receivers), 'utf-8')
#添加正文,直接读取cfile
msg.attach(MIMEText(open(cfile, 'r').read(), 'html', _charset='utf-8'))
#添加附件,取详细日志,此处不需要
#part = MIMEApplication(open(newfile, 'rb').read())
#part.add_header('Content-Disposition', 'attachment', filename="alert_{0}.log".format(dbname))
#msg.attach(part)
#发送邮件
try:
s = smtplib.SMTP()
s.connect(mail_host, 25)
s.login(mail_user, mail_passwd)
s.sendmail(mail_user, receivers, msg.as_string())
return True
except:
return False
cfile = '/tmp/mail_slave_status.html'
get_slave_status(dbhosts, dbuser, dbpasswd, dbport, cfile)
if os.path.getsize(cfile):
if send_mail(cfile):
print("send success")
else:
print("send failed")
else:
print("no abnormal slave")
既然是案例,就只选择了一个比较大众化的脚本。如果想要设计其他类型的告警邮件,也可以参考这个脚本,然后根据需求来简单修改一下就行,毕竟核心的东西都是相通的。