def ToBackup(self, get): #try: result = panelMysql.panelMysql().execute("show databases") isError = self.IsSqlError(result) if isError: return isError id = get['id'] name = public.M('databases').where("id=?", (id, )).getField('name') root = public.M('config').where('id=?', (1, )).getField('mysql_root') if not os.path.exists(session['config']['backup_path'] + '/database'): public.ExecShell('mkdir -p ' + session['config']['backup_path'] + '/database') if not self.mypass(True, root): return public.returnMsg(False, '数据库配置文件获取失败,请检查MySQL配置文件是否存在') fileName = name + '_' + time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.sql.gz' backupName = session['config']['backup_path'] + '/database/' + fileName public.ExecShell( "/www/server/mysql/bin/mysqldump --default-character-set=" + public.get_database_character(name) + " --force --opt \"" + name + "\" | gzip > " + backupName) if not os.path.exists(backupName): return public.returnMsg(False, 'BACKUP_ERROR') self.mypass(False, root) sql = public.M('backup') addTime = time.strftime('%Y-%m-%d %X', time.localtime()) sql.add('type,name,pid,filename,size,addtime', (1, fileName, id, backupName, 0, addTime)) public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS", (name, )) return public.returnMsg(True, 'BACKUP_SUCCESS')
def backup_database_data(self, id): result = panelMysql.panelMysql().execute("show databases") isError = self.IsSqlError(result) if isError: return isError name = public.M('databases').where("id=?", (id, )).getField('name') root = public.M('config').where('id=?', (1, )).getField('mysql_root') if not os.path.exists('/www/server/panel/BTPanel/static' + '/database'): public.ExecShell('mkdir -p ' + '/www/server/panel/BTPanel/static' + '/database') self.mypass(True, root) path_id = ''.join( random.sample(string.ascii_letters + string.digits, 20)) fileName = path_id + 'DATA' + name + '_' + time.strftime( '%Y%m%d_%H%M%S', time.localtime()) + '.sql.gz' backupName = '/www/server/panel/BTPanel/static' + '/database/' + fileName public.ExecShell( "/www/server/mysql/bin/mysqldump --default-character-set=" + public.get_database_character(name) + " --force --opt \"" + name + "\" | gzip > " + backupName) if not os.path.exists(backupName): return public.returnMsg(False, 'BACKUP_ERROR') self.mypass(False, root) sql = public.M('backup') addTime = time.strftime('%Y-%m-%d %X', time.localtime()) sql.add('type,name,pid,filename,size,addtime', (1, fileName, id, backupName, 0, addTime)) public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS", (name, )) return backupName
def backup_database(self,db_name,dfile = None,save=3): self.echo_start() if not dfile: fname = 'db_{}_{}.sql.gz'.format(db_name,public.format_date("%Y%m%d_%H%M%S")) dfile = os.path.join(self._path,'database',fname) else: fname = os.path.basename(dfile) dpath = os.path.dirname(dfile) if not os.path.exists(dpath): os.makedirs(dpath,384) import panelMysql if not self._db_mysql:self._db_mysql = panelMysql.panelMysql() d_tmp = self._db_mysql.query("select sum(DATA_LENGTH)+sum(INDEX_LENGTH) from information_schema.tables where table_schema='%s'" % db_name) p_size = self.map_to_list(d_tmp)[0][0] if p_size == None: self.echo_error('The specified database [ {} ] has no data!'.format(db_name)) return character = public.get_database_character(db_name) self.echo_info('Backup database:{}'.format(db_name)) self.echo_info("Database size: {}".format(public.to_size(p_size))) self.echo_info("Database character set: {}".format(character)) disk_path,disk_free,disk_inode = self.get_disk_free(dfile) self.echo_info("Partition {} available disk space is: {}, available Inode is: {}".format(disk_path,public.to_size(disk_free),disk_inode)) if disk_path: if disk_free < p_size: self.echo_error("The available disk space of the target partition is less than {}, and the backup cannot be completed. Please increase the disk capacity or change the default backup directory on the settings page!".format(public.to_size(p_size))) return False if disk_inode < self._inode_min: self.echo_error("The available Inode of the target partition is less than {}, and the backup cannot be completed. Please increase the disk capacity or change the default backup directory on the settings page!".format(self._inode_min)) return False stime = time.time() self.echo_info("Start exporting database: {}".format(public.format_date(times=stime))) if os.path.exists(dfile): os.remove(dfile) self.mypass(True) public.ExecShell("/www/server/mysql/bin/mysqldump --default-character-set="+ character +" --force --hex-blob --opt " + db_name + " 2>"+self._err_log+"| gzip > " + dfile) self.mypass(False) gz_size = os.path.getsize(dfile) if gz_size < 400: self.echo_error("Database export failed!") self.echo_info(public.readFile(self._err_log)) return False self.echo_info("Database backup completed, took {:.2f} seconds, compressed package size: {}".format(time.time() - stime,public.to_size(gz_size))) if self._cloud: self.echo_info("Uploading to {}, please wait ...".format(self._cloud._title)) if self._cloud.upload_file(dfile, 'database'): self.echo_info("Successfully uploaded to {}".format(self._cloud._title)) else: self.echo_error('Error: File upload failed, skip this backup!') if os.path.exists(dfile): os.remove(dfile) return False filename = dfile if self._cloud: filename = self._cloud._name self.echo_info("Database has been backed up to: {}".format(dfile)) if os.path.exists(self._err_log): os.remove(self._err_log) pid = public.M('databases').where('name=?',(db_name)).getField('id') pdata = { 'type': '1', 'name': fname, 'pid': pid, 'filename': filename, 'addtime': public.format_date(), 'size': os.path.getsize(dfile) } public.M('backup').insert(pdata) if self._cloud: if not self._is_save_local: if os.path.exists(dfile): os.remove(dfile) self.echo_info("User settings do not retain local backups, deleted {}".format(dfile)) #清理多余备份 if not self._cloud: backups = public.M('backup').where("type=? and pid=? and filename LIKE '%/%'",('1',pid)).field('id,name,filename').select() else: backups = public.M('backup').where('type=? and pid=? and filename=?',('1',pid,filename)).field('id,name,filename').select() self.echo_info(str(backups)) self.delete_old(backups,save,'database') self.echo_end() return dfile
def backupDatabase(self, name, count): sql = db.Sql() path = sql.table('databases').where('name=?', (name, )).getField('id') startTime = time.time() if not path: endDate = time.strftime('%Y/%m/%d %X', time.localtime()) log = u"数据库[" + name + u"]不存在!" print(u"★[" + endDate + "] " + log) print( u"----------------------------------------------------------------------------" ) return backup_path = sql.table('config').where( "id=?", (1, )).getField('backup_path') + '/database' if not os.path.exists(backup_path): public.ExecShell("mkdir -p " + backup_path) filename = backup_path + "/Db_" + name + "_" + time.strftime( '%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz" import re mysql_root = sql.table('config').where("id=?", (1, )).getField('mysql_root') mycnf = public.readFile('/etc/my.cnf') rep = "\[mysqldump\]\nuser=root" sea = "[mysqldump]\n" subStr = sea + "user=root\npassword="******"\n" mycnf = mycnf.replace(sea, subStr) if len(mycnf) > 100: public.writeFile('/etc/my.cnf', mycnf) public.ExecShell( "/www/server/mysql/bin/mysqldump --default-character-set=" + public.get_database_character(name) + " --force --opt " + name + " | gzip > " + filename) if not os.path.exists(filename): endDate = time.strftime('%Y/%m/%d %X', time.localtime()) log = u"数据库[" + name + u"]备份失败!" print(u"★[" + endDate + "] " + log) print( u"----------------------------------------------------------------------------" ) return mycnf = public.readFile('/etc/my.cnf') mycnf = mycnf.replace(subStr, sea) if len(mycnf) > 100: public.writeFile('/etc/my.cnf', mycnf) endDate = time.strftime('%Y/%m/%d %X', time.localtime()) outTime = time.time() - startTime pid = sql.table('databases').where('name=?', (name, )).getField('id') sql.table('backup').add('type,name,pid,filename,addtime,size', (1, os.path.basename(filename), pid, filename, endDate, os.path.getsize(filename))) log = u"数据库[" + name + u"]备份成功,用时[" + str(round(outTime, 2)) + u"]秒" public.WriteLog(u'计划任务', log) print("★[" + endDate + "] " + log) print(u"|---保留最新的[" + count + u"]份备份") print(u"|---文件名:" + filename) #清理多余备份 backups = sql.table('backup').where( 'type=? and pid=? and filename!=? and filename!=? and filename!=? and filename!=? and filename!=?', ('1', pid, 'alioss', 'txcos', 'upyun', 'qiniu', 'ftp')).field('id,filename').select() num = len(backups) - int(count) if num > 0: for backup in backups: public.ExecShell("rm -f " + backup['filename']) sql.table('backup').where('id=?', (backup['id'], )).delete() num -= 1 print(u"|---已清理过期备份文件:" + backup['filename']) if num < 1: break
def backup_database(self,db_name,dfile = None,save=3): self.echo_start() if not dfile: fname = 'db_{}_{}.sql.gz'.format(db_name,public.format_date("%Y%m%d_%H%M%S")) dfile = os.path.join(self._path,'database',fname) else: fname = os.path.basename(dfile) dpath = os.path.dirname(dfile) if not os.path.exists(dpath): os.makedirs(dpath,384) error_msg = "" import panelMysql if not self._db_mysql:self._db_mysql = panelMysql.panelMysql() d_tmp = self._db_mysql.query("select sum(DATA_LENGTH)+sum(INDEX_LENGTH) from information_schema.tables where table_schema='%s'" % db_name) try: p_size = self.map_to_list(d_tmp)[0][0] except: error_msg = public.getMsg('DB_CONN_ERR') self.echo_error(error_msg) self.send_failture_notification(error_msg) return False if p_size == None: error_msg = public.getMsg('DB_BACKUP_ERR',(db_name,)) self.echo_error(error_msg) self.send_failture_notification(error_msg) return False character = public.get_database_character(db_name) self.echo_info(public.getMsg('DB_BACKUP',(db_name,))) self.echo_info(public.getMsg("DB_SIZE",(public.to_size(p_size),))) self.echo_info(public.getMsg("DB_CHARACTER",(character,))) disk_path,disk_free,disk_inode = self.get_disk_free(dfile) self.echo_info(public.getMsg( "PARTITION_INFO",( disk_path,str(public.to_size(disk_free)),str(disk_inode) ) )) if disk_path: if disk_free < p_size: error_msg = public.getMsg("PARTITION_LESS_THEN",( str(public.to_size(p_size),) )) self.echo_error(error_msg) self.send_failture_notification(error_msg) return False if disk_inode < self._inode_min: error_msg = public.getMsg("INODE_LESS_THEN",(self._inode_min,)) self.echo_error(error_msg) self.send_failture_notification(error_msg) return False stime = time.time() self.echo_info(public.getMsg("EXPORT_DB",(public.format_date(times=stime),))) if os.path.exists(dfile): os.remove(dfile) #self.mypass(True) try: password = public.M('config').where('id=?',(1,)).getField('mysql_root') os.environ["MYSQL_PWD"] = password backup_cmd = "/www/server/mysql/bin/mysqldump -E -R --default-character-set="+ character +" --force --hex-blob --opt " + db_name + " -u root" + " 2>"+self._err_log+"| gzip > " + dfile public.ExecShell(backup_cmd) except Exception as e: raise finally: os.environ["MYSQL_PWD"] = "" #public.ExecShell("/www/server/mysql/bin/mysqldump --default-character-set="+ character +" --force --hex-blob --opt " + db_name + " 2>"+self._err_log+"| gzip > " + dfile) #self.mypass(False) gz_size = os.path.getsize(dfile) if gz_size < 400: error_msg = public.getMsg("EXPORT_DB_ERR") self.echo_error(error_msg) self.send_failture_notification(error_msg) self.echo_info(public.readFile(self._err_log)) return False compressed_time = str('{:.2f}'.format(time.time() - stime)) self.echo_info( public.getMsg("COMPRESS_TIME",(str(compressed_time), str(public.to_size(gz_size)) )) ) if self._cloud: self.echo_info(public.getMsg("BACKUP_UPLOADING",(self._cloud._title,))) if self._cloud.upload_file(dfile, 'database'): self.echo_info(public.getMsg("BACKUP_UPLOAD_SUCCESS",(self._cloud._title,))) else: if hasattr(self._cloud, "error_msg"): if self._cloud.error_msg: error_msg = self._cloud.error_msg if not error_msg: error_msg = public.getMsg('BACKUP_UPLOAD_FAILED') self.echo_error(error_msg) if os.path.exists(dfile): os.remove(dfile) remark = "Backup to " + self._cloud._title self.send_failture_notification(error_msg, remark=remark) return False filename = dfile if self._cloud: filename = dfile + '|' + self._cloud._name + '|' + fname self.echo_info(public.getMsg("DB_BACKUP_TO",(dfile,))) if os.path.exists(self._err_log): os.remove(self._err_log) pid = public.M('databases').where('name=?',(db_name)).getField('id') pdata = { 'type': '1', 'name': fname, 'pid': pid, 'filename': filename, 'addtime': public.format_date(), 'size': os.path.getsize(dfile) } public.M('backup').insert(pdata) if self._cloud: _not_save_local = True save_local = 0 if self.cron_info: save_local = self.cron_info["save_local"] if save_local: _not_save_local = False else: if self._is_save_local: _not_save_local = False pdata = { 'type': '1', 'name': fname, 'pid': pid, 'filename': dfile, 'addtime': public.format_date(), 'size': os.path.getsize(dfile) } public.M('backup').insert(pdata) if _not_save_local: if os.path.exists(dfile): os.remove(dfile) self.echo_info(public.getMsg("BACKUP_DEL",(dfile,))) else: self.echo_info(public.getMsg('KEEP_LOCAL')) #清理多余备份 if not self._cloud: backups = public.M('backup').where("type=? and pid=? and filename NOT LIKE '%|%'",('1',pid)).field('id,name,filename').select() else: backups = public.M('backup').where('type=? and pid=? and filename LIKE "%{}%"'.format(self._cloud._name),('1',pid)).field('id,name,filename').select() self.delete_old(backups,save,'database') self.echo_end() return dfile
def backup_database(self, db_name, dfile=None, save=3): self.echo_start() if not dfile: fname = 'db_{}_{}.sql.gz'.format( db_name, public.format_date("%Y%m%d_%H%M%S")) dfile = os.path.join(self._path, 'database', fname) else: fname = os.path.basename(dfile) dpath = os.path.dirname(dfile) if not os.path.exists(dpath): os.makedirs(dpath, 384) import panelMysql if not self._db_mysql: self._db_mysql = panelMysql.panelMysql() d_tmp = self._db_mysql.query( "select sum(DATA_LENGTH)+sum(INDEX_LENGTH) from information_schema.tables where table_schema='%s'" % db_name) p_size = self.map_to_list(d_tmp)[0][0] if p_size == None: self.echo_error('指定数据库 `{}` 没有任何数据!'.format(db_name)) return character = public.get_database_character(db_name) self.echo_info('备份数据库:{}'.format(db_name)) self.echo_info("数据库大小:{}".format(public.to_size(p_size))) self.echo_info("数据库字符集:{}".format(character)) disk_path, disk_free, disk_inode = self.get_disk_free(dfile) self.echo_info("分区{}可用磁盘空间为:{},可用Inode为:{}".format( disk_path, public.to_size(disk_free), disk_inode)) if disk_path: if disk_free < p_size: self.echo_error( "目标分区可用的磁盘空间小于{},无法完成备份,请增加磁盘容量,或在设置页面更改默认备份目录!".format( public.to_size(p_size))) return False if disk_inode < self._inode_min: self.echo_error( "目标分区可用的Inode小于{},无法完成备份,请增加磁盘容量,或在设置页面更改默认备份目录!".format( self._inode_min)) return False stime = time.time() self.echo_info("开始导出数据库:{}".format(public.format_date(times=stime))) if os.path.exists(dfile): os.remove(dfile) self.mypass(True) public.ExecShell( "/www/server/mysql/bin/mysqldump --default-character-set=" + character + " --force --hex-blob --opt " + db_name + " 2>" + self._err_log + "| gzip > " + dfile) self.mypass(False) gz_size = os.path.getsize(dfile) if gz_size < 400: self.echo_error("数据库导出失败!") self.echo_info(public.readFile(self._err_log)) return False self.echo_info("数据库备份完成,耗时{:.2f}秒,压缩包大小:{}".format( time.time() - stime, public.to_size(gz_size))) if self._cloud: self.echo_info("正在上传到{},请稍候...".format(self._cloud._title)) if self._cloud.upload_file(dfile, 'database'): self.echo_info("已成功上传到{}".format(self._cloud._title)) else: self.echo_error('错误:文件上传失败,跳过本次备份!') if os.path.exists(dfile): os.remove(dfile) return False filename = dfile if self._cloud: filename = dfile + '|' + self._cloud._name + '|' + fname self.echo_info("数据库已备份到:{}".format(dfile)) if os.path.exists(self._err_log): os.remove(self._err_log) pid = public.M('databases').where('name=?', (db_name)).getField('id') pdata = { 'type': '1', 'name': fname, 'pid': pid, 'filename': filename, 'addtime': public.format_date(), 'size': os.path.getsize(dfile) } public.M('backup').insert(pdata) if self._cloud: if not self._is_save_local: if os.path.exists(dfile): os.remove(dfile) self.echo_info("用户设置不保留本地备份,已删除{}".format(dfile)) #清理多余备份 if not self._cloud: backups = public.M('backup').where( "type=? and pid=? and filename NOT LIKE '%|%'", ('1', pid)).field('id,name,filename').select() else: backups = public.M('backup').where( 'type=? and pid=? and filename LIKE "%{}%"'.format( self._cloud._name), ('1', pid)).field('id,name,filename').select() self.delete_old(backups, save, 'database') self.echo_end() return dfile