事情需要,对公司的MYSQL数据库举办备份,遇上方才开始学python,看了一套简朴的python解说视频,简朴的写了个备份剧本,小我私家暗示 对python 的class 、function、build-in function 、私有变量、全局变量 等等,该怎么用,啥时候用等 毫无观念 ,仅此记录一下吧,也接待途经的pythoner见教。
小我私家已知的一些问题:
1、该剧本必需要求 mysql设置文件内的所有行为 key=value的名目,而且不能存在多余的注释,不然ConfigParser模块理会设置文件时会堕落,由于没研究过ConfigParser是不是有容错的要领可以挪用,也没时间写容错处理惩罚,而是通过整理my.ini 设置文件使其切合ConfigParser的要求办理的。后头会附上我用的mysql设置文件。
2、大量利用类私有成员变量,因为完全不知道python 变量、类要领、等等啥时候该私有化,以及有啥区别,只知道类私有成员变量在此外剧本中import 可能担任时,是不行见的。
3、较量多的举办文件操纵,以及传值操纵,今朝只担保按正确名目传值没问题,没有做多余的容错处理惩罚。 4、大量的在举办字符串拼接,第一次写运维相关剧本,由于要挪用系统呼吁,和通报许多参数,也不会subprocess模块,不知作别人写运维剧本都详细咋做,就直接拼接了。
5、其他未知的bug、未发明的逻辑错误等等。
情况:
– Server : Dell PowerEdge T110
– OS: CentOS 6.3_x86_64
– PythonVersion: 2.7.3
– MysqlVersion: 5.5.28 linux x86_64
MysqlBackupScript.py
#!/usr/bin/env python # coding: utf8 # script MysqlBackupScript # by Becareful # version v1.0 """ This scripts provides auto backup mysql(version == 5.5.x) database . """ import os import sys import datetime #用于生成备份文件的日期 import linecache #用于读取文件的指定行 import ConfigParser #理会mysql设置文件 class DatabaseArgs(object): """ """ __MYSQL_BASE_DIR = r'/usr/local/mysql' #mysql安装目次 __MYSQL_BIN_DIR = __MYSQL_BASE_DIR + '/bin' #mysql二进制目次 __MYSQL_CONFIG_FILE = r'/usr/local/mysql/my.cnf' #mysql设置文件 __ONEDAY = datetime.timedelta(days=1) #一天的时长,用于计较下面的前一天和后一天日期 __TODAY = datetime.date.today() #当天日期名目为 YYYY-MM-DD __YESTERDAY = __TODAY - __ONEDAY #计较昨天日期 __TOMORROW = __TODAY + __ONEDAY #计较来日诰日日期 __WEEKDAY = __TODAY.strftime('%w') #计较当天是一礼拜的礼拜几 __MYSQL_DUMP_ARGS = { #用一个字典存储mysqldump 呼吁备份数据库的参数 'MYISAM': ' -v -E -e -R --triggers -F -n --opt --master-data=2 --hex-blob -B ', 'INNODB': ' -v -E -e -R --triggers -F --single-transaction -n --opt --master-data=2 --hex-blob -B ' } __DUMP_COMMAND = __MYSQL_BIN_DIR + '/mysqldump' #mysqldump 呼吁的 路径 用于dump mysql数据 __FLUSH_LOG_COMMAND = __MYSQL_BIN_DIR + '/mysqladmin' #mysqladmin 呼吁的路径 ,用于执行 flush-logs 生成天天增量binlog __BACKUP_DIR = r'/backup/' # 指定备份文件存放的目次 __PROJECTNAME = 'example' # 指定需要备份的数据库对应的项目名,未来会生成 projectname-YYYY-MM-DD.sql 等文件 __DATABASE_LIST = [] # 指定需要备份的数据库名,可以是多个,利用列表 __HOST = 'localhost' __PORT = 3306 __USERNAME = 'root' __PASSWORD = '' __LOGINARGS = '' # 假如在localhost登岸,需要暗码,可以设定登岸的参数,详细在下面有说明 __LOGFILE = __BACKUP_DIR + '/backup.logs' def __init__(self, baseDir=__MYSQL_BASE_DIR, backDir=__BACKUP_DIR, engine='MYISAM', projectName=__PROJECTNAME, dbList=__DATABASE_LIST, host=__HOST, port=__PORT, user=__USERNAME, passwd=__PASSWORD): """ 实例化工具时传入的参数,如不传入默认利用类的私有成员变量作为默认值 :param baseDir: :param backDir: :param engine: :param projectName: :param dbList: :param host: :param port: :param user: :param passwd: """ self.__MYSQL_BASE_DIR = baseDir self.__BACKUP_DIR = backDir self.__PROJECTNAME = projectName self.__DATABASE_LIST = dbList self.__HOST = host self.__PORT = port self.__USERNAME = user self.__PASSWORD = passwd self.__ENGINE = self.__MYSQL_DUMP_ARGS[engine] #下面界说了如需登岸时,参数 其实就是生成 这样的名目 “-hlocalhost -uroot --password=‘xxxx’” self.__LOGINARGS = " -h" + self.__HOST + " -P" + str( self.__PORT) + " -u" + self.__USERNAME + " --password='" + self.__PASSWORD + "'" self.checkDatabaseArgs() #挪用查抄函数 def __getconfig(self, cnf=__MYSQL_CONFIG_FILE, item=None): # 理会mysql设置文件的小函数,简朴封装了下,传入一个值作为my.cnf的key去查找对应的value __mycnf = ConfigParser.ConfigParser() __mycnf.read(cnf) try: return __mycnf.get("mysqld", item) except BaseException, e: sys.stderr.write(str(e)) sys.exit(1) def __getBinlogPath(self): # 取天天需要增量备份的binlog日志的绝对路径,从mysql的binlog.index文件取倒数第二行 __BINLOG_INDEX = self.__getconfig(item='log-bin') + '.index' if not os.path.isfile(__BINLOG_INDEX): sys.stderr.write('BINLOG INDEX FILE: [' + __BINLOG_INDEX + ' ] NOT FOUND! \n') sys.exit(1) else: try: __BINLOG_PATH = linecache.getline(__BINLOG_INDEX, len(open(__BINLOG_INDEX, 'r').readlines()) - 1) linecache.clearcache() except BaseException, e: sys.stderr.write(str(e)) sys.exit(1) return __BINLOG_PATH.strip() def flushDatabaseBinlog(self): # 挪用此函数,将会执行 mysqladmin flush-logs ,刷新binlog日志 return os.popen(self.__FLUSH_LOG_COMMAND + self.__LOGINARGS + ' flush-logs') def dumpDatabaseSQL(self): #|通过mysqladmin 对指定命据库举办全备 if not os.path.isfile(self.__BACKUP_DIR + '/' + self.__PROJECTNAME + '/' + str(self.__YESTERDAY) + '-' + self.__PROJECTNAME + '.sql'): return os.popen(self.__DUMP_COMMAND + self.__LOGINARGS + self.__ENGINE + ' '.join( self.__DATABASE_LIST) + ' >> ' + self.__BACKUP_DIR + '/' + self.__PROJECTNAME + '/' + str( self.__YESTERDAY) + '-' + self.__PROJECTNAME + '.sql') else: sys.stderr.write('Backup File [' + str(self.__YESTERDAY) + '-' + self.__PROJECTNAME + '.sql] already exists.\n') def dumpDatabaseBinlog(self):#通过copy2() 将需要备份的binlog日志复制到指定备份目次 if not os.path.isfile(self.__BACKUP_DIR + '/' + self.__PROJECTNAME + '/' + str(self.__YESTERDAY) + '-' + os.path.split(self.__getBinlogPath())[1]): from shutil import copy2 try: copy2(self.__getBinlogPath(), self.__BACKUP_DIR + '/' + self.__PROJECTNAME + '/' + str(self.__YESTERDAY) + '-' + os.path.split(self.__getBinlogPath())[1]) except BaseException, e: sys.stderr.write(str(e)) else: sys.stderr.write('Binlog File [' + str(self.__YESTERDAY) + '-' + os.path.split(self.__getBinlogPath())[1] + '] already exists\n' ) def checkDatabaseArgs(self): #对一些须要条件举办查抄 __rv = 0 if not os.path.isdir(self.__MYSQL_BASE_DIR): #查抄指定的mysql安装目次是否存在 sys.stderr.write('MYSQL BASE DIR: [ ' + self.__MYSQL_BASE_DIR + ' ] NOT FOUND\n') __rv += 1 if not os.path.isdir(self.__BACKUP_DIR): #查抄指定的备份目次是否存在,如不存在自动建设 sys.stderr.write('BACKUP DIR: [ ' + self.__BACKUP_DIR + '/' + self.__PROJECTNAME + ' ] NOT FOUND ,AUTO CREATED\n') os.makedirs(self.__BACKUP_DIR + '/' + self.__PROJECTNAME) if not os.path.isfile(self.__MYSQL_CONFIG_FILE): #查抄mysql设置文件是否存在 sys.stderr.write('MYSQL CONFIG FILE: [' + self.__MYSQL_CONFIG_FILE + ' ] NOT FOUND\n') __rv += 1 if not os.path.isfile(self.__DUMP_COMMAND): #查抄备份数据库时利用的mysqldump呼吁是否存在 sys.stderr.write('MYSQL DUMP COMMAND: [' + self.__DUMP_COMMAND + ' ] NOT FOUND\n') __rv += 1 if not os.path.isfile(self.__FLUSH_LOG_COMMAND): #查抄刷新mysql binlog日志利用的mysqladmin呼吁是否存在 sys.stderr.write('MYSQL FLUSH LOG COMMAND: [' + self.__DUMP_COMMAND + ' ] NOT FOUND\n') __rv += 1 if not self.__DATABASE_LIST: #查抄需要备份的数据库列表是否存在 sys.stderr.write('Database List is None \n') __rv += 1 if __rv: # 判定返回值,由于上述任何一步查抄失败,城市导致 __rv 值 +1 ,只要最后__rv != 0就直接退出了。 sys.exit(1) def crontab(): # 利用字典,来举办相关参数通报,并实例化工具,挪用相关要领举办操纵 zabbix = { 'baseDir': '/usr/local/mysql/', 'backDir': '/backup/', 'projectName': 'Monitor', 'dbList': ['zabbix'], 'host': 'localhost', 'port': 3306, 'user': 'root', 'passwd': 'xxxxxxx' } monitor = DatabaseArgs(**zabbix) monitor.dumpDatabaseSQL() monitor.dumpDatabaseBinlog() monitor.flushDatabaseBinlog() if __name__ == '__main__': crontab()
my.cnf
[client] port = 3306 socket = /mysql/var/db.socket [mysqld] socket = /mysql/var/db.socket datadir = /mysql/db/ skip-external-locking = 1 skip-innodb = 0 key_buffer_size = 256M max_allowed_packet = 10M table_open_cache = 2048 sort_buffer_size = 4M read_buffer_size = 4M read_rnd_buffer_size = 8M myisam_sort_buffer_size = 64M myisam_max_sort_file_size = 1G myisam_repair_threads = 1 myisam_recover = DEFAULT thread_cache_size = 32 query_cache_size = 32M query_cache_min_res_unit = 2k bulk_insert_buffer_size = 64M tmp_table_size = 128M thread_stack = 192K skip-name-resolve = 1 max_connections = 65500 default-storage-engine = myisam federated = 0 server-id = 1 slave-skip-errors = all #log = /var/log/sql_query.log slow-query-log = 1 slow-query-log-file = /mysql/log/sql_query_slow.log long-query-time = 5 log-queries-not-using-indexes = 1 log-slow-admin-statements = 1 log-bin = /mysql/var/log/binlog/bin-log log-error = /mysql/var/log/mysql.err master-info-file = /mysql/var/log/master.info relay-log = /mysql/var/log/relay-bin/relay-bin relay-log-index = /mysql/var/log/relay-bin/relay-bin.index relay-log-info-file = /mysql/var/log/relay-bin/relay-bin.info binlog_cache_size = 8M binlog_format = MIXED max_binlog_cache_size = 20M max_binlog_size = 1G binlog-ignore-db = mysql binlog-ignore-db = performance_schema binlog-ignore-db = information_schema replicate-ignore-db = mysql replicate-ignore-db = performance_schema replicate-ignore-db = information_schema innodb_data_home_dir = /mysql/ibdata/ innodb_data_file_path = ibdata:156M:autoextend innodb_log_group_home_dir = /mysql/ibdata/ log-slave-updates = 0 back_log = 512 transaction_isolation = READ-COMMITTED max_heap_table_size = 246M interactive_timeout = 120 wait_timeout = 120 innodb_additional_mem_pool_size = 16M innodb_buffer_pool_size = 512M innodb_file_io_threads = 4 innodb_thread_concurrency = 8 innodb_flush_log_at_trx_commit = 2 innodb_log_buffer_size = 16M innodb_log_file_size = 128M innodb_log_files_in_group = 3 innodb_max_dirty_pages_pct = 90 innodb_lock_wait_timeout = 120 innodb_file_per_table = 1 innodb_open_file = 327500 open_files_limit = 327500 [mysqldump] quick = 1 max_allowed_packet = 50M [mysql] auto-rehash = 1 socket = /mysql/var/db.socket safe-updates = 0 [myisamchk] key_buffer_size = 256M sort_buffer_size = 256M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout = 100
最终生成的备份目次布局是这样的
[root@zabbix backup]# find ./ ./ ./Monitor ./Monitor/2013-03-16-bin-log.000008 ./Monitor/2013-03-14-bin-log.000006 ./Monitor/2013-03-16-Monitor.sql ./Monitor/2013-03-15-Monitor.sql ./Monitor/2013-03-15-bin-log.000007 ./Monitor/2013-03-14-Monitor.sql ~END~