云萌主云应用官方论坛

标题: mydumper备份代码 [打印本页]

作者: 骑单车的小女孩    时间: 2016-12-30 00:32
标题: mydumper备份代码
来源:http://www.open-open.com/code/view/1443669081080
  1.    #!/usr/bin/phthon  
  2.       
  3.       
  4.     import os  
  5.     import time  
  6.     import commands  
  7.     import shutil  
  8.     import threading  
  9.     from os.path import join, getsize  
  10.     import MySQLdb as mydb  
  11.       
  12.       
  13.     # 备份目录  
  14.     baseDir = "/data2/backup/backup_data/"  
  15.       
  16.       
  17.     # ns 或 wx;  备份后是否要压缩(mydumper 自带压缩功能),要压缩 True,否则 False.  
  18.     idc = 'ns'; isZip = True  
  19.       
  20.       
  21.     # 备份失败是否重试 ,True 则重试,不重试 设 False, retry_sleep 多久后才开始重试(秒)  
  22.     is_errRetryBackup = True; retry_sleep = 300  
  23.       
  24.       
  25.     # 备份日期  
  26.     backup_date = time.strftime("%Y%m%d")  
  27.       
  28.       
  29.     # 备份命令  
  30.     cmd  = "/usr/local/bin/mydumper -h %s -u root -p password? -P %s %s -t 5 -o %s"  
  31.       
  32.       
  33.     '''''
  34.     功能描述:
  35.       1. mydumper 远程批量备份, 备份列表由配置文件提供
  36.       2. 可按要求对备份是否压缩(mydumper 自动压缩)
  37.       3. 备份失败允许再尝试备份一次
  38.       4. 备份信息写入数据库
  39.     '''  
  40.     def main():  
  41.         thread_pool = []  
  42.       
  43.       
  44.         # 是否启用压缩  
  45.         zip = '-c' if isZip == True else ''  
  46.       
  47.       
  48.         # 从配置文件读取 ip, 名称, 端口, 并拼凑备份语句  
  49.         #f = open('/data2/backup/cnf/other_list.cnf', 'r')  
  50.         f = open('/data/other_list.cnf', 'r')  
  51.         for lines in f.readlines():  
  52.             if (not lines.startswith('#') and len(lines.strip()) > 0):  
  53.                 str = lines.split()  
  54.                 host, businessName, port, isMaster = str[0], str[1], str[2], str[3]  
  55.                 # 业务文件夹不存在则创建  
  56.                 dir = baseDir + '/' + businessName;  
  57.                 if (not os.path.exists(dir)):  
  58.                      os.makedirs(dir)  
  59.       
  60.       
  61.                 dir += "/%s%s" % (businessName, backup_date)  
  62.                 # 业务目录: dir , 备份目录: dir/name+备份日期  
  63.                 strcmd  = cmd % (host, port, zip, dir)  
  64.       
  65.       
  66.                 th = threading.Thread(target = mydumper, args =(strcmd, dir, businessName, host, port, is_errRetryBackup, int(isMaster)))  
  67.                 thread_pool.append(th)  
  68.       
  69.       
  70.         if (thread_pool):  
  71.             for t in thread_pool:  
  72.                 t.daemon = True  
  73.                 t.start()  
  74.             for t in thread_pool:  
  75.                 t.join()  
  76.       
  77.       
  78.     def mydumper(sCmd, backupDir, businessName, host, port, is_Retry, isMaster):  
  79.         master_host = ""; backup_host = host; name = businessName; port = port; backup_type = 1; file = "";  
  80.         start_time = ""; stop_time = ""; returncode = 0; file_size = 0; slave_statement = ""; std_err = "";  
  81.       
  82.       
  83.         start_time = time.strftime("%Y%m%d%H%M%S")  
  84.       
  85.       
  86.         # 清除可能遗留的备份  
  87.         if (os.path.exists(backupDir)):  
  88.             shutil.rmtree(backupDir)  
  89.       
  90.       
  91.         # 执行备份  
  92.         returncode, std_err = execute(sCmd)  
  93.       
  94.       
  95.         stop_time = time.strftime("%Y%m%d%H%M%S")  
  96.       
  97.       
  98.         if (returncode == 0):  
  99.             # 备份 std_err 返回不为空也视为出错。  
  100.             if (std_err.strip() != ""):  
  101.                 returncode = 123456  
  102.             else:  
  103.                 # 获取 change master to 信息,再次校验备份是否有效  
  104.                 returncode, std_err, master_host, slave_statement = statement(backupDir, backup_host, isMaster)  
  105.       
  106.       
  107.                 if (returncode == 0):  
  108.                     file = backupDir  
  109.       
  110.       
  111.         if (returncode != 0):  
  112.             # 异常备份标记为: 日期 + _ERR  
  113.             errDir = backupDir + "_ERR"  
  114.             os.rename(backupDir, errDir)  
  115.             file = errDir  
  116.       
  117.       
  118.         # 获取备份大小  
  119.         file_size = getDirsize(file)  
  120.       
  121.       
  122.         if (len(std_err) > 255):  
  123.             std_err = std_err[:250] + "..."  
  124.       
  125.       
  126.         my_args  = [idc, master_host, backup_host, name, port, backup_type, file, start_time, stop_time, returncode, file_size, slave_statement, std_err]  
  127.       
  128.       
  129.         # 写入数据库  
  130.         call_proc(my_args)  
  131.       
  132.       
  133.         # 备份失败是否需要重备? 重备允许一次.  
  134.         if (is_Retry == True and returncode != 0):  
  135.             time.sleep(retry_sleep)  
  136.       
  137.       
  138.             oldfile = sCmd.split('-o')[1]  
  139.             pos = oldfile.rfind("/") + 1  
  140.       
  141.       
  142.             # 获取备份全路径, 备份文件标记为重备 字样  
  143.             retry_file = oldfile[:pos] + "ReBackup-" + oldfile[pos:]  
  144.       
  145.       
  146.             retryCmd = sCmd.replace(oldfile,  retry_file)  
  147.       
  148.       
  149.             # 重备开始  
  150.             mydumper(retryCmd, retry_file.strip(), name, host, port, False, isMaster)  
  151.       
  152.       
  153.     def getDirsize(path):  
  154.         # 获取备份文件夹大小  
  155.         size = 0L  
  156.         for root, dirs, files in os.walk(path):  
  157.             size += sum([getsize(join(root, name)) for name in files])  
  158.         return (size)  
  159.       
  160.       
  161.     def statement(path, backup_host, isMaster):  
  162.         '''''
  163.         功能: 从 metadata 读取change master to 信息
  164.         1. 备份过程: 会先生成: metadata.partial, 完成后metadata.partial会重名为: metadata 并写入备份完成时间
  165.         2. metadata 分3段:
  166.            (1) Started dump: 备份开始时间.
  167.            (2) master 的log-file 和 log-pos 信息 (必有); slave 的host、log-file 和 log-pos 信息 (备机是slave 才有)
  168.            (3) Finished dump: 备份结束时间
  169.         3. 返回错码, master_host 和 change master to 信息
  170.         '''  
  171.         path += "/metadata"; sMetadata = ""; master_host = ""; er_code = 654321; er_info = "%s not exists !!!" % (path)  
  172.       
  173.       
  174.         if (os.path.exists(path)):  
  175.             if (isMaster != 1):  
  176.                 # 备机是 slave  
  177.                 num = 3  
  178.                 sFinds = "SLAVE STATUS"  
  179.             else:  
  180.                 num = 2  
  181.                 sFinds = "MASTER STATUS"  
  182.       
  183.       
  184.             f = open(path, 'r')  
  185.             rows = f.readlines(); i = 100; lst =[]  
  186.             for s in rows:  
  187.                 if (s.find(sFinds) > 0):  
  188.                     i = 1; continue  
  189.       
  190.       
  191.                 if (i <= num):  
  192.                     lst.append(s.split(':')[1].strip())  
  193.                     i += 1  
  194.       
  195.       
  196.             if (isMaster == 1):  
  197.                 # 备机是 master  
  198.                 master_host = backup_host  
  199.                 log_file, log_pos = lst;  
  200.             else:  
  201.                 # 备机是 slave  
  202.                 master_host, log_file, log_pos = lst;  
  203.       
  204.       
  205.             er_code = 0  
  206.             er_info = ""  
  207.             sMetadata = "CHANGE MASTER TO MASTER_HOST='%s',MASTER_LOG_FILE='%s',MASTER_LOG_POS=%s,MASTER_USER='rep_user',MASTER_PASSWORD='meizu.com'" % (master_host, log_file, log_pos )  
  208.       
  209.       
  210.         return (er_code, er_info, master_host, sMetadata)  
  211.       
  212.       
  213.     def execute(cmd):  
  214.         '''''
  215.         1.执行 shell 命令
  216.         2.返回执行信息 (returncode = 0 则执行成功, std_err 为报错的错误信息)
  217.         '''  
  218.         try:  
  219.             returncode, std_err = commands.getstatusoutput(cmd)  
  220.             return (returncode, std_err)  
  221.         except os.error, e:  
  222.             # 异常返回 1001 错误  
  223.             return (1001, e)  
  224.       
  225.       
  226.     def call_proc(my_args):  
  227.         # 备份信息写入数据库  
  228.         try:  
  229.             conn = mydb.connect(host = '127.0.0.1', user = 'test', passwd = 'zxc/213?', db = 'meizu_item')  
  230.             cur  = conn.cursor()  
  231.       
  232.       
  233.             cur.callproc('sp_backup_i',[my_args[0], my_args[1], my_args[2], my_args[3], my_args[4], my_args[5], my_args[6], my_args[7], my_args[8], my_args[9], my_args[10], my_args[11], my_args[12]])  
  234.             conn.commit()  
  235.         except mydb.Error, e:  
  236.             pass  
  237.             # print "Mysql Error %d: %s" % (e.args[0], e.args[1])  
  238.         finally:  
  239.             cur.close(); conn.close()  
  240.       
  241.       
  242.     if __name__ == '__main__':  
  243.         main()  
复制代码






欢迎光临 云萌主云应用官方论坛 (https://www.yunmengzhu.com/) Powered by Discuz! X3.4