经典的MySQL 数据备份校验daemon程序

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2011 Justin Santa Barbara
# All Rights Reserved.
# Copyright (c) 2010 Citrix Systems, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.
import smtplib
import os,sys,time,fcntl,struct
import ConfigParser
import commands
import traceback
import socket
import shutil
import sys
import re
try:
    from email.mime.multipart import MIMEMultipart
except:
    from email.MIMEMultipart import MIMEMultipart
try:
    from email.mime.text import MIMEText
except:
    from email.MIMEText import MIMEText
try:
    from hashlib import md5
except:
    from md5 import md5
CONFIG_PATH = "/etc/rsyncd.conf"
def _load_cfg(section = None):
    '''
    load config section from CONFIG_PATH
    '''
    global CONFIG_PATH
    config = ConfigParser.ConfigParser()
    if os.path.isfile(CONFIG_PATH):
        config.read(CONFIG_PATH)
        sections = config.sections()
        if section and section in sections:
            return dict(config.items(section))
        elif not section:
            rst = dict()
            for sec in sections:
                rst[sec] = dict(config.items(sec))
            return rst
        else:
            return dict()
def load_cfg(sections = []):
    '''
    from cfg format to dict
    :params sections The section list in cfg
    return a dict with all options
    '''
    rst = dict()
    if not sections:
        return _load_cfg()
    for sec in sections:
        rst[sec] = _load_cfg(sec)
    return rst
def logging(item,level,mes):
    logpath = '/var/log/kxtools/'
    if not os.path.exists(logpath):
        os.makedirs(logpath)
    fp = open('%s/kxbackup.log'%logpath,'a')
    fp.write('%s - %s - %s - %s \n'%(time.ctime(),item,level,mes))
    fp.close()
"""Access file md5 value"""
def MD5(fname):
    filemd5 = ""
    try:
        file = open(fname, "rb")
        md5f = md5()
        strs = ""
        while True:
            strs = file.read(8096)
            if not strs:
                break
            md5f.update(strs)
        filemd5 = md5f.hexdigest()
        file.close()
        return filemd5
    except:
        logging('MySQL Check','ERROR',traceback.format_exc())
def get_em_ipaddr(dev):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    IP = socket.inet_ntoa(fcntl.ioctl(
           s.fileno(),
           0x8915,  # SIOCGIFADDR
           struct.pack('24s',dev)
    )[20:24])
    return IP
def ipaddr():
    """
    Get host name, ip
    return(hostname, ip)
    """
    def _get_ipaddr():
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(("8.8.8.8", 8000))
            return s.getsockname()[0]
        except:
            logging('MySQL Check','ERROR',traceback.format_exc())
        s.close()
    return (socket.gethostname(), _get_ipaddr())
def tracert(ip):
    count = 0
    for t in range(10):
        sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        sock.settimeout(10)
        try:
            sock.connect((ip,873))
            count += 1
        except socket.error,e:
            pass
        time.sleep(1)
    if count >= 6:
        return 0
    else:
        return 1
class  SendMail(object):
    def __init__ (self):
        self.smtpserver = 'smtp.163.com'
        self.fro = '[email protected]'
        self.c_code = 'UTF-8'
        self.port = 25
        self.auth = '[email protected]'
        self.pawd = '11111111@123'
    ''' Send Email'''
    def sendmail(self,to,subject,content,cc='',files=[]):
        msg = MIMEMultipart()
        msg['Subject'] = subject
        txt = MIMEText(content)
        msg.attach(txt)
        hd = smtplib.SMTP(self.smtpserver,self.port)
        hd.ehlo()
        hd.starttls()
        hd.ehlo()
        if self.auth and self.pawd:
            hd.login(self.auth,self.pawd)
        for t in to.split(","):
            hd.sendmail(self.fro,t, msg.as_string())
        if cc:
            for t in cc.split(","):
                hd.sendmail(self.fro,t, msg.as_string())
        hd.close()
class CheckMySQL(object):
    def __init__(self):
        version = 1.0
    def checkRsyncConfig(self):
        # Rsync configuration check
        fp = open('/etc/rsyncd.conf','r').readlines()
        for n,s in enumerate(fp):
            if n == 0:
                if s[0] != '[':
                    fp.insert(0,'[global]\n')
        f = open('/etc/rsyncd.conf','w')
        f.writelines(fp)
        f.close()
    def checkFile(self):
        # Directory traversal, find today compared with yesterday's file
        backupPath  = load_cfg()['yttx']['path']
        os.chdir(backupPath)
        CTIME = time.strftime('%Y%m%d')
        files= dict()
        # Define the keys
        for f in os.listdir(backupPath):
            stamp_time, file_kyes = self._get_file_ctime(f)
            if (time.time() - stamp_time) <= 86400:
                files[file_kyes] = list()
        # According to the date of classified documents
        for f in os.listdir(backupPath):
            stamp_time , file_ctime = self._get_file_ctime(f)
            stamp_ctime = time.time()
            for tm in files.keys():
                #print file_ctime,f
                if tm == file_ctime and (stamp_ctime - stamp_time) <= 86400:
                    files[tm].append(f)
        # Check the file MD5
        today_file =dict()
        ystday_file = dict()
        Ttime = time.strftime("%Y%m%d")
        Ytime = time.strftime("%Y%m%d",time.localtime((time.time() - 86400)))
        for f  in os.listdir(backupPath):
            if Ttime ==f.split('_')[0]:
                ip = f.split('_')[1]
                today_file[ip]=f
            elif Ytime == f.split('_')[0]:
                ip = f.split('_')[1]
                ystday_file[ip] = f
            else:
                pass
        # Read the latest IP list
        backup_list = '/data0/backup_mysql.txt'
        if not os.path.exists(backup_list):
            utils.COMM("touch %s" %backup_list)
        fp = open('/data0/backup_mysql.txt','r').readlines()
        ips = [i.strip() for i in fp]
        fail_ip = list()
        done_ip = list()
        # Call Func md5
        for ip in ips:
            if ip  in today_file:
                if not self._checkMD5(backupPath,today_file[ip]):
                    fail_ip.append(ip)
                else:
                    done_ip.append(ip)
            else:
                fail_ip.append(ip)
        # Determine whether is empty,
        # If not empty, calls the SendMail class
        done_mes = str()
        if done_ip:
            for ip in done_ip:
                done_mes += "host %s MySQL backup is successful \n" %ip
        done_info = "\nBackup Successful: \n" + done_mes
        ret = str()
        if fail_ip:
            for ip in fail_ip:
                ret += "host %s MySQL backup is failure \n" %ip
        mess = "\nPlease check the specific reason for the error \n" + "E-mail : [email protected], [email protected],[email protected] \n" + "Q Q : 11111,2222222,33333 "
        back_time = "\nCheck Time: %s \n" %time.ctime()
        mes = done_info  + "\nBackup Failure:\n"  + ret + back_time +  mess
        send = SendMail()
        # Subject
        subject = "MySQL Backup %s information" %ipaddr()[1]
        cc = '[email protected],[email protected],[email protected]'
        send.sendmail('[email protected]',subject,mes,cc='')
    def _checkMD5(self,backupPath,files):
        file = backupPath + '/' + files
        try:
            md5sun = file.split("_")[-1].split('.')[0]
        except:
            return False
        fmd5sun = MD5(file)
        if fmd5sun  == md5sun:
            return True
        else:
            return False
    def _get_file_ctime(self,f):
        # return time stamp, YY-MM-DD
        st_ctime = os.stat(f).st_mtime
        return st_ctime , time.strftime('%Y%m%d',time.localtime(st_ctime))
    def DeleteFile(self):
        # Delete file from 8 day ago
        reserve = '/data0/reserve/'
        if not os.path.exists(reserve):
            os.makedirs(reserve)
        backuPath  = load_cfg()['yttx']['path']
        keep_file = list()
        delete_file = list()
        os.chdir(backuPath)
        ctimes = time.time()
        keep_time  = 691200
        for f in os.listdir(backuPath):
            create_time = os.stat(f).st_ctime
            if ctimes - create_time >= keep_time:
                try:
                    shutil.move(f,reserve)
                except:
                    shutil.move(f,'/dev/null')
                logging('MySQL Check','INFO',"Delete file %s"%f)
if __name__ == "__main__":
    sc = CheckMySQL()
    sc.checkRsyncConfig()
    sc.checkFile()
    sc.DeleteFile()


你可能感兴趣的:(struct,OS,SYS,time,MimeMultipart,fcntl)