您的位置:首页 > 数据库 > MySQL

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

2014-05-16 18:31 393 查看
# 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 = 'kxbackup@163.com'
self.c_code = 'UTF-8'
self.port = 25
self.auth = 'kxbackup@163.com'
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 : 222@222.222.com, 3333@222.222.com,444@222.2222.com \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 = '2222@222.222.com,333@222.222.com,444@222.222.com'
send.sendmail('kxbackup@163.com',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()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息