用Python对MySQL同步状态进行监控

用Python对MySQL同步状态进行监控

使用Python对MySQL数据库服务器是否可访问,及主从同步是否中断进行监控,是一件非常简单的事情。感谢Python给我们带来了如此简单,强大,快捷的开发环境。

本文使用到的Python模块

使用telnetlib校验服务器是否可被访问

使用SMTP向管理员发送通知邮件

使用MySQL官方的驱动对数据库进行访问

使用optparse实现命令行参数的提取

实现原理

使用optparse模块获取命令行参数。读取defaults-file设置文件内容(如果存在),使用参数覆盖defaults-file的值(如果传递参数,如:–host, –user, –to之类)。

直接去连MySQL等待是否能进行访问的返回结果太慢了,所以使用telnet对服务器的连通性进行验证。可以设置等待时间,可控性高一些。

当服务器工作正常,使用MySQL与服务器进行连接,获取主从同步的状态。

将获取服务器的异常状态信息(服务器无法访问,主从同步的状态中断),使用SMTP发送给管理员,并把造成中断同步的异常信息一同发送到管理员的邮箱中。



Created with Rapha?l 2.1.2starttelnet host:portconnect?slave statusslave?endnotifyyesnoyesno



slavecheckpoint.py

coding=utf-8
"""
数据库同步状态侦测
MySQL数据库同步复制状态监测脚本。可配合Linux下的crond进行定时监测。如果同步
状态异常,侧使用邮件通知管理员,并将造成同步中断的错误信息也包含到邮件当中,管
理员可即时通过错误信息直接定位异常。

实例:
python slavecheckpoint.py --defaults-file=/etc/slave.cnf [email protected]

===FILE:slave.cnf===========
[config]
smtp_host=smtp.163.com
from=消息中心<[email protected]>
host=localhost
"""

import mysql.connector
from mysql.connector import errorcode
import telnetlib
import smtplib
from email.mime.text import MIMEText
import optparse
from ConfigParser import ConfigParser
import os,time,sys

class SlaveStatu:
    __instance__ = None
    __error__ = []

    def __init__(self,*args,**kwargs):
        self.__config__ = {
            "host":"localhsot",
            "user":"root",
            "password":"",
            "port":3306,
            "smtp_host":"localhost",
            "smtp_user":"",
            "smtp_password":"",
            "from":"[email protected]",
            "to":""
        }

        #优先读取设置文件中的值
        if not kwargs["defaults_file"] is None:
            defaults_file = self.__read_defaults_file__( kwargs["defaults_file"] )
            del kwargs["defaults_file"]

        #使用参数的设置去覆盖设置文件的值
        for key,val in kwargs.items():
            if not val is None and len(val) > 0:
                self.__config__[key] = val

    def __configParseMySQL__(self):
        """
        提取数据库的设置
        :return: dict
        """
        return {
            "host"     : self.__config__["host"],
            "port"     : self.__config__["port"],
            "user"     : self.__config__["user"],
            "password" : self.__config__["password"]
        }

    def __configParseSMTP__(self):
        """
        提取SMTP邮件设置
        :return: dict
        """
        return {
            "smtp_host": self.__config__["smtp_host"],
            "smtp_user": self.__config__["smtp_user"],
            "smtp_password": self.__config__["smtp_password"],
            "from": self.__config__["from"],
            "to": self.__config__["to"]
        }

    def __read_defaults_file__( self, filePath ):
        """
        加载设置文件设置的值
        :param filePath: 设置文件路径
        :return:
        """
        section = "config"
        if os.path.exists( filePath ):
            cnf = ConfigParser()
            cnf.read( filePath )
            options = cnf.options( section )

            for key in options:
                self.__config__[key] = cnf.get( section, key )

    def telnet( self, host, port, timeout=5 ):
        """
        测试服务器地址和端口是否畅通
        :param host: 服务器地址
        :param port: 服务器端口
        :param timeout: 测试超时时间
        :return: Boolean
        """
        try:
            tel = telnetlib.Telnet( host, port, timeout )
            tel.close()
            return True
        except:
            return False

    def connect(self):
        """
        创建数据库链接
        """
        try:
            config = self.__configParseMySQL__()
            if self.telnet( config["host"],config["port"]):
                self.__instance__ = mysql.connector.connect( **config )
                return True
            else:
                raise Exception("unable connect")
        except:
            self.__error__.append( "无法连接服务器主机: {host}:{port}".format( host=config[
                    "host"], port=config["port"]) )
            return False

    def isSlave(self):
        """
        数据库同步是否正常
        :return: None同步未开启,False同步中断,True同步正常
        """
        cur = self.__instance__.cursor(dictionary=True)
        cur.execute("SHOW SLAVE STATUS")
        result = cur.fetchone()
        cur.close()

        if result:
            if result["Slave_SQL_Running"] == "Yes" and result["Slave_IO_Running"] == "Yes":
                return True
            else:
                if result["Slave_SQL_Running"] == "No":
                    self.__error__.append( result["Last_SQL_Error"] )
                else:
                    self.__error__.append( result["Last_IO_Error"] )
                return False

    def get_last_error(self):
        """
        获取第一个错误信息
        :return: String
        """
        if self.__error__:
            return self.__error__.pop(0)

    def notify(self,title,message):
        """
        发送消息提醒
        :param title: 消息的标题
        :param message: 消息的内容
        :return:
        """
        msg    = [title,message]
        pool   = []
        notify = notify_email( self.__configParseSMTP__() )
        pool.append( notify )

        for item in pool:
            item.ring( msg )

    def close(self):
        """
        关闭数据库链接
        """
        if self.__instance__:
            self.__instance__.close()

class notify_email(object):
    def __init__(self,config):
        self.config = config

    def ring(self, message=[]):
        subject = message.pop(0)
        messageBody = "".join( message )
        mailList = self.config["to"].split(";")
        datetime = time.strftime("%Y-%m-%d %H:%M:%S")
        for to in mailList:
            body = """
            <p>管理员<strong>{admin}</strong>,你好:</p>
            <p style="text-indent:2em;">收到这封邮件说明你的数据库同步出现异常,请您及时进行处理。</p>
            <p>异常信息:<br />{body}</p>
            <p style="text-align:right;">{date}</p>
            """.format( admin=to, body=messageBody, date=datetime )

            msg            = MIMEText( body, "html", "utf-8" )
            msg["From"]    = self.config["from"]
            msg["To"]      = to
            msg["Subject"] = subject
            smtp           = smtplib.SMTP()

            smtp.connect( self.config["smtp_host"] )
            if self.config.has_key("smtp_user"):
                smtp.login( self.config["smtp_user"], self.config["smtp_password"] )
            smtp.sendmail( self.config["from"], to, msg.as_string() )
            smtp.quit()

if __name__ == "__main__":
    #命令行参数列表
    usage = """usage: MySQLStat [options]"""

    opt = optparse.OptionParser(usage=usage)
    opt.add_option("-H","--host",dest="host",help="MySQL host (default: localhost)")
    opt.add_option("-u","--user",dest="user",help="MySQL user")
    opt.add_option("-p","--password",dest="password",help="MySQL password")
    opt.add_option("-P","--port",dest="port",help="MySQL port (default: 3306)")
    opt.add_option("","--smtp_host",dest="smtp_host",help="SMTP host (default: localhost)")
    opt.add_option("","--smtp_user",dest="smtp_user",help="SMTP user")
    opt.add_option("","--smtp_password",dest="smtp_password",help="SMTP password")
    opt.add_option("","--from",dest="from",help="Email from")
    opt.add_option("","--to",dest="to",help="Email to")
    opt.add_option("","--defaults-file",dest="defaults_file",help="config file path")
    (options,args) = opt.parse_args()

    options = options.__dict__
    Statu = SlaveStatu( **options )
    subject = "服务中心异常信息提醒"
    if Statu.connect() is False or Statu.isSlave() is False:
        Statu.notify( subject, Statu.get_last_error() )
    Statu.close()


server1.cnf 设置文件内容

[config]
smtp_host=smtp.aliyun.com
smtp_user=[email protected]
smtp_password=xxxxxx
from=管理中心<[email protected]>
host=xxx.xxx.xxx.xxx
user=root
password=123456


完成了以上的配置之后,我们在定时任务里添加一条任务,就可以让程序为我们监控MySQL的服务器状态了。

crontab设置

*/2 * * * * python slavecheckpoint.py --defaults-file=server1.cnf [email protected].com
时间: 2024-10-05 10:56:54

用Python对MySQL同步状态进行监控的相关文章

nagios 实现Mysql 主从同步状态的监控

一.系统环境 主机名 IP nagios 192.168.15.111 mysql_s 192.168.15.21 二.操作步骤 2.1 mysql_s端的配置 2.1.1 编写check_mysql_slave监控脚本 cd /usr/local/nagios/libexec   #切换到nagios 监控插件所在目录 vim check_mysql_slave       #开始编写mysql_slave监控脚本 注意:监控脚本中的mysql账户一定要新建一个,并设置有限的权限.   2.1

利用Python监测MySQL主从状态

探测MySQL主从状态,如果从未同步,则发邮件通知运维人员.利用定时任务秒级监测! # -*- coding: utf-8 -* #! /usr/bin/env python from fabric.api import * from fabric.colors import * from fabric.context_managers import * from fabric.contrib.console import confirm import string import smtplib

从show slave status 中判断mysql同步状态

slave status 中检查同步状态: 1.sql线程和io线程显示yes Slave_IO_Running: Yes Slave_SQL_Running: Yes 2. Master_Log_File 和  Relay_Master_Log_File 相等 3. Read_Master_Log_Pos 和 Exec_Master_Log_Pos 相等 4. Slave_SQL_Running_State: 的状态为: Slave_SQL_Running_State: Slave has r

MySQL 同步状态

Exec_Master_Log_Pos: The position of the last event executed by the SQL thread from the master's binary log (Relay_Master_Log_File). (Relay_Master_Log_File, Exec_Master_Log_Pos) in the master's binary log corresponds to (Relay_Log_File, Relay_Log_Pos

zabbix自定义监控mysql主从状态,并做邮件告警

 通过zabbix自定义监控mysql主从状态,并做邮件告警 分析: mysql主要是通过主从来提供安全性,一个完整的主从体系,就应该包括数据同步.开启二进制日志.全备.还有对Slave_IO_Running和Slave_SQL_Running两个线程的实时监测,并做告警,而zabbix监控软件就提供了很好的方法:对于zabbix这个监控软件,个人来说也是比较熟悉,现在的企业们都基本用的是zabbix软件来做系统的资源的监控,zabbix的强大不仅仅体现于,它自身自带的监控模板比较全面,而是通过

监控mysql主从同步状态是否异常,如果异常,则发生短信或邮寄给管理员

阶段1:开发一个守护进程脚本每30秒实现检测一次. 阶段2:如果同步出现如下错误号(1158,1159,1008,1007,1062),请跳过错误 阶段3:请使用数组技术实现上述脚本(获取主从判断及错误号部分) [[email protected] ~]# mysql -u root -proot -e "show slave status\G;" *************************** 1. row ***************************       

python实战系列之MySQL主从状态监控(09)

1. 需求说明 由于openstack底层中MySQL使用了主从AB复制,为了监控数据库的主从状态信息,需要对MySQL的主从状态进行监控,从而保障数据库底层正常运行,为openstack提供更好的功能.本文对数据库执行监控,具体内容参考下面. 2. 程序内容 #!/usr/bin/env python #_*_ coding:utf8 _*_ #author:happyliu #用于监控MySQL主从复制状态 import os import sys import os.path import

使用zabbix监控mysql主从状态

公司mysql架构为一主多从.在日常使用过程中我们经常会遇到主从不同步的情况,为了及时处理此问题现使用zabbix监控mysql主从状态并设置触发器,如有异常则发送邮件报警. 我们都知道使用命令"show slave status \G"可以查看mysql从的状态,下面用脚本方式检查其状态. 在mysql-slave中进入zabbix-agent目录创建脚本文件. cat mysql_slave_status.sh #!/bin/bash /usr/local/mysql/bin/my

监控mysql同步,修改DNS解析

#!/usr/bin/env python import time,MySQLdb from subprocess import Popen from subprocess import PIPE import dns.query import dns.message import dns.tsig import dns.tsigkeyring import dns.update def set_dns(ip_list): key=dns.tsigkeyring.from_text({"cui.