diff --git a/class/core/files_api.py b/class/core/files_api.py index 54d3882a4..aa61b8956 100755 --- a/class/core/files_api.py +++ b/class/core/files_api.py @@ -987,6 +987,33 @@ class files_api: return mw.getJson(data) + def execShellApi(self, get): + # 执行SHELL命令 + shell = request.form.get('shell', '').strip() + path = request.form.get('path', '').strip() + disabled = ['vi', 'vim', 'top', 'passwd', 'su'] + tmp = shell.split(' ') + if tmp[0] in disabled: + return mw.returnJson(False, '禁止执行[{}]'.format(tmp[0])) + shellStr = '''#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH +cd %s +%s +''' % (path, shell) + mw.writeFile('/tmp/panelShell.sh', shellStr) + mw.execShell( + 'nohup bash /tmp/panelShell.sh > /tmp/panelShell.pl 2>&1 &') + return mw.returnJson(True, 'ok') + + def getExecShellMsgApi(self, get): + # 取SHELL执行结果 + fileName = '/tmp/panelShell.pl' + if not os.path.exists(fileName): + return '' + status = not mw.processExists('bash', None, '/tmp/panelShell.sh') + return mw.returnJson(status, mw.getNumLines(fileName, 200)) + def __get_stats(self, filename, path=None): filename = filename.replace('//', '/') try: diff --git a/class/core/mw.py b/class/core/mw.py index 27d5b5c59..cd8f7223c 100755 --- a/class/core/mw.py +++ b/class/core/mw.py @@ -1631,6 +1631,31 @@ def getSshDir(): return '/root/.ssh' +def processExists(pname, exe=None, cmdline=None): + # 进程是否存在 + try: + import psutil + pids = psutil.pids() + for pid in pids: + try: + p = psutil.Process(pid) + if p.name() == pname: + if not exe and not cmdline: + return True + else: + if exe: + if p.exe() == exe: + return True + if cmdline: + if cmdline in p.cmdline(): + return True + except: + pass + return False + except: + return True + + def createRsa(): # ssh-keygen -t rsa -P "" -C "midoks@163.com" ssh_dir = getSshDir() diff --git a/plugins/migration_api/index.py b/plugins/migration_api/index.py index 92db4e1a1..47b87b0aa 100755 --- a/plugins/migration_api/index.py +++ b/plugins/migration_api/index.py @@ -8,6 +8,8 @@ import re import hashlib import json +from requests_toolbelt import MultipartEncoder + sys.path.append(os.getcwd() + "/class/core") import mw @@ -20,8 +22,12 @@ class classApi: __MW_KEY = 'app' __MW_PANEL = 'http://127.0.0.1:7200' + _buff_size = 1024 * 1024 * 2 + _REQUESTS = None _SPEED_FILE = None + _INFO_FILE = None + _SYNC_INFO = None # 如果希望多台面板,可以在实例化对象时,将面板地址与密钥传入 def __init__(self, mw_panel=None, mw_key=None): @@ -34,6 +40,8 @@ class classApi: self._REQUESTS = requests.session() self._SPEED_FILE = getServerDir() + '/config/speed.json' + self._INFO_FILE = getServerDir() + '/config/sync_info.json' + self._SYNC_INFO = self.get_sync_info(None) # 计算MD5 def __get_md5(self, s): @@ -63,6 +71,25 @@ class classApi: return mw.returnJson(False, '连接超时!') return mw.returnJson(False, '连接服务器失败!') + def get_sync_info(self, args): + # 获取要被迁移的网站、数据库 + if not os.path.exists(self._INFO_FILE): + return mw.returnJson(False, '迁移信息不存在!') + sync_info = json.loads(mw.readFile(self._INFO_FILE)) + if not args: + return sync_info + result = [] + for i in sync_info['sites']: + i['type'] = "网站" + result.append(i) + for i in sync_info['databases']: + i['type'] = "数据库" + result.append(i) + for i in sync_info['paths']: + i['type'] = "目录" + result.append(i) + return result + def write_speed(self, key, value): # 写进度 if os.path.exists(self._SPEED_FILE): @@ -96,6 +123,15 @@ class classApi: except Exception as e: return result + def sendPlugins(self, name, func, args): + url = '/plugins/run' + + data = {} + data['name'] = name + data['func'] = func + data['args'] = json.dumps(args).replace(": ", ":").replace(", ", ",") + return self.send(url, data) + def get_mode_and_user(self, path): '''取文件或目录权限信息''' data = {} @@ -109,39 +145,166 @@ class classApi: data['user'] = str(stat.st_uid) return data + def error(self, error_msg, is_exit=False): + # 发生错误 + write_log("=" * 50) + write_log("|-发生时间: {}".format(mw.formatDate())) + write_log("|-错误信息: {}".format(error_msg)) + if is_exit: + write_log("|-处理结果: 终止迁移任务") + sys.exit(0) + write_log("|-处理结果: 忽略错误, 继续执行") + def upload_file(self, sfile, dfile, chmod=None): # 上传文件 if not os.path.exists(sfile): write_log("|-指定目录不存在{}".format(sfile)) return False pdata = self.__get_key_data() - pdata['f_name'] = os.path.basename(dfile) - pdata['f_path'] = os.path.dirname(dfile) - pdata['f_size'] = os.path.getsize(sfile) - pdata['f_start'] = 0 + pdata['name'] = os.path.basename(dfile) + pdata['path'] = os.path.dirname(dfile) + pdata['size'] = os.path.getsize(sfile) + pdata['start'] = 0 if chmod: mode_user = self.get_mode_and_user(os.path.dirname(sfile)) pdata['dir_mode'] = mode_user['mode'] + ',' + mode_user['user'] mode_user = self.get_mode_and_user(sfile) pdata['file_mode'] = mode_user['mode'] + ',' + mode_user['user'] f = open(sfile, 'rb') + return self.send_file(pdata, f) - def send_file(self, f): - pass + def close_sync(self, args): + # 取消迁移 + mw.execShell("kill -9 {}".format(self.get_pid())) + mw.execShell( + "kill -9 $(ps aux|grep index.py|grep -v grep|awk '{print $2}')") + # 删除迁移配置 + time.sleep(1) + if os.path.exists(self._INFO_FILE): + os.remove(self._INFO_FILE) + if os.path.exists(self._SPEED_FILE): + os.remove(self._SPEED_FILE) + return mw.returnJson(True, '已取消迁移任务!') + + def send_file(self, pdata, f): + success_num = 0 # 连续发送成功次数 + max_buff_size = int(1024 * 1024 * 2) # 最大分片大小 + min_buff_size = int(1024 * 32) # 最小分片大小 + err_num = 0 # 连接错误计数 + max_err_num = 10 # 最大连接错误重试次数 + up_buff_num = 5 # 调整分片的触发次数 + timeout = 60 # 每次发送分片的超时时间 + split_num = 0 + split_done = 0 + total_time = 0 + self.write_speed('done', "正在传输文件") + self.write_speed('size', pdata['size']) + self.write_speed('used', 0) + self.write_speed('speed', 0) + write_log("|-上传文件[{}], 总大小:{}, 当前分片大小为:{}".format(pdata['name'], + toSize(pdata['size']), toSize(self._buff_size))) + while True: + buff_size = self._buff_size + max_buff = int(pdata['size'] - pdata['start']) + if max_buff < buff_size: + buff_size = max_buff + files = {"blob": f.read(buff_size)} + start_time = time.time() - def save(self): - # 保存迁移配置 - mw.writeFile(self._INFO_FILE, json.dumps(self._SYNC_INFO)) + try: + url = self.__MW_PANEL + '/api/files/upload_segment' + res = self._REQUESTS.post( + url, data=pdata, files=files, timeout=30000) + + success_num += 1 + err_num = 0 + # 连续5次分片发送成功的情况下尝试调整分片大小, 以提升上传效率 + if success_num > up_buff_num and self._buff_size < max_buff_size: + self._buff_size = int(self._buff_size * 2) + success_num = up_buff_num - 3 # 如再顺利发送3次则继续提升分片大小 + if self._buff_size > max_buff_size: + self._buff_size = max_buff_size + write_log( + "|-发送顺利, 尝试调整分片大小为: {}".format(toSize(self._buff_size))) + except Exception as e: + times = time.time() - start_time + total_time += times + ex = str(ex) + if ex.find('Read timed out') != -1 or ex.find('Connection aborted') != -1: + # 发生超时的时候尝试调整分片大小, 以确保网络情况不好的时候能继续上传 + self._buff_size = int(self._buff_size / 2) + if self._buff_size < min_buff_size: + self._buff_size = min_buff_size + success_num = 0 + write_log( + "|-发送超时, 尝试调整分片大小为: {}".format(toSize(self._buff_size))) + continue + + # 如果连接超时 + if ex.find('Max retries exceeded with') != -1 and err_num <= max_err_num: + err_num += 1 + write_log("|-连接超时, 第{}次重试".format(err_num)) + time.sleep(1) + continue + + # 超过重试次数 + write_log("|-上传失败, 跳过本次上传任务") + write_log(mw.getTracebackInfo()) + return False + + result = res.json() + times = time.time() - start_time + total_time += times + + if type(result) == int: + if result == split_done: + split_num += 1 + else: + split_num = 0 + split_done = result + if split_num > 10: + write_log("|-上传失败, 跳过本次上传任务") + return False + if result > pdata['size']: + write_log("|-上传失败, 跳过本次上传任务") + return False + self.write_speed('used', result) + self.write_speed('speed', int(buff_size / times)) + write_log("|-已上传 {},上传速度 {}/s, 共用时 {}分{:.2f}秒, {:.2f}%".format(toSize(float(result)), toSize( + buff_size / times), int(total_time // 60), total_time % 60, (float(result) / float(pdata['size']) * 100))) + pdata['start'] = result # 设置断点 + else: + if not result['status']: # 如果服务器响应上传失败 + write_log(result['msg']) + return False + + if pdata['size']: + self.write_speed('used', pdata['size']) + self.write_speed('speed', int(buff_size / times)) + write_log("|-已上传 {},上传速度 {}/s, 共用时 {}分{:.2f}秒, {:.2f}%".format(toSize(float(pdata['size'])), toSize( + buff_size / times), int(total_time // 60), total_time % 60, (float(pdata['size']) / float(pdata['size']) * 100))) + break + + self.write_speed('total_size', pdata['size']) + self.write_speed('end_time', int(time.time())) + write_log("|-总耗时:{} 分钟, {:.2f} 秒, 平均速度:{}/s".format(int(total_time // + 60), total_time % 60, toSize(pdata['size'] / total_time))) + return True def state(self, stype, index, state, error=''): # 设置状态 - self._SYNC_INFO[stype][index]['state'] = state - self._SYNC_INFO[stype][index]['error'] = error - if self._SYNC_INFO[stype][index]['state'] != 1: - self._SYNC_INFO['speed'] += 1 + # print(self._SYNC_INFO) + # self._SYNC_INFO[stype][index]['state'] = state + # self._SYNC_INFO[stype][index]['error'] = error + # if self._SYNC_INFO[stype][index]['state'] != 1: + # self._SYNC_INFO['speed'] += 1 self.save() + def save(self): + # 保存迁移配置 + mw.writeFile(self._INFO_FILE, json.dumps(self._SYNC_INFO)) + def format_domain(self, domain): # 格式化域名 domains = [] @@ -167,8 +330,8 @@ class classApi: result = self.send('/site/add', pdata) if not result['status']: err_msg = '站点[{}]创建失败, {}'.format(siteInfo['name'], result['msg']) - # self.state('sites', index, -1, err_msg) - # self.error(err_msg) + self.state('sites', index, -1, err_msg) + self.error(err_msg) return False return True @@ -185,43 +348,286 @@ class classApi: data = getCfgData() sites = data['ready']['sites'] for i in range(len(sites)): - siteInfo = mw.M('sites').where('name=?', (sites[i],)).field( - 'id,name,path,ps,status,edate,addtime').find() + try: + siteInfo = mw.M('sites').where('name=?', (sites[i],)).field( + 'id,name,path,ps,status,edate,addtime').find() + + if not siteInfo: + err_msg = "指定站点[{}]不存在!".format(sites[i]) + self.state('sites', i, -1, err_msg) + self.error(err_msg) + continue + pid = siteInfo['id'] + + siteInfo['port'] = mw.M('domain').where( + 'pid=? and name=?', (pid, sites[i],)).getField('port') + + siteInfo['domain'] = mw.M('domain').where( + 'pid=? and name!=?', (pid, sites[i])).field('name,port').select() + + if self.send_site(siteInfo, i): + self.state('sites', i, 2) + write_log("=" * 50) + except Exception as e: + self.error(mw.getTracebackInfo()) + + def getConf(self, mtype='mysql'): + path = mw.getServerDir() + '/' + mtype + '/etc/my.cnf' + return path + + def getSocketFile(self, mtype='mysql'): + file = self.getConf(mtype) + content = mw.readFile(file) + rep = 'socket\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + def getDbPort(self, mtype='mysql'): + file = self.getConf(mtype) + content = mw.readFile(file) + rep = 'port\s*=\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + + def getDbConn(self, mtype='mysql', db='databases'): + my_db_pos = mw.getServerDir() + '/' + mtype + conn = mw.M(db).dbPos(my_db_pos, 'mysql') + return conn + + def getMyConn(self, mtype='mysql'): + # pymysql + db = mw.getMyORM() + + db.setPort(self.getDbPort(mtype)) + db.setSocket(self.getSocketFile(mtype)) + pwd = self.getDbConn(mtype, 'config').where( + 'id=?', (1,)).getField('mysql_root') + db.setPwd(pwd) + return db + + def getDbList(self): + conn = self.getDbConn() + alist = conn.field( + 'id,name,username,password,ps').order("id desc").select() + return alist + + def getDbInfo(self, name): + conn = self.getDbConn() + info = conn.field( + 'id,name,username,password,ps').where('name=?', (name,)).find() + return info + + def mapToList(self, map_obj): + # map to list + try: + if type(map_obj) != list and type(map_obj) != str: + map_obj = list(map_obj) + return map_obj + except: + return [] - if not siteInfo: - err_msg = "指定站点[{}]不存在!".format(sites[i]) - # self.state('sites', i, -1, err_msg) - # self.error(err_msg) - continue - pid = siteInfo['id'] + # 取数据库权限 + def getDatabaseAccess(self, name): + return '127.0.0.1' + try: + conn = self.getMyConn() + users = conn.query( + "select Host from mysql.user where User='" + name + "' AND Host!='localhost'") + users = self.mapToList(users) + if len(users) < 1: + return "127.0.0.1" + accs = [] + for c in users: + accs.append(c[0]) + userStr = ','.join(accs) + return userStr + except: + return '127.0.0.1' + + def isSqlError(self, mysqlMsg): + # 检测数据库执行错误 + mysqlMsg = str(mysqlMsg) + if "MySQLdb" in mysqlMsg: + return mw.returnData(False, 'DATABASE_ERR_MYSQLDB') + if "2002," in mysqlMsg or '2003,' in mysqlMsg: + return mw.returnData(False, 'DATABASE_ERR_CONNECT') + if "using password:" in mysqlMsg: + return mw.returnData(False, 'DATABASE_ERR_PASS') + if "Connection refused" in mysqlMsg: + return mw.returnData(False, 'DATABASE_ERR_CONNECT') + if "1133" in mysqlMsg: + return mw.returnData(False, 'DATABASE_ERR_NOT_EXISTS') + return None + + def getDatabaseCharacter(self, db_name): + try: + conn = self.getMyConn() + tmp = conn.query("show create database `%s`" % db_name.strip(), ()) + # print(tmp) + c_type = str(re.findall(r"SET\s+([\w\d-]+)\s", tmp[0][1])[0]) + c_types = ['utf8', 'utf-8', 'gbk', 'big5', 'utf8mb4'] + if not c_type.lower() in c_types: + return 'utf8' + return c_type + except Exception as e: + # print(str(e)) + return 'utf8' + + # 创建远程数据库 + def create_database(self, dbInfo, index): + pdata = {} + pdata['name'] = dbInfo['name'] + pdata['db_user'] = dbInfo['username'] + pdata['password'] = dbInfo['password'] + pdata['dataAccess'] = dbInfo['accept'] + if dbInfo['accept'] != '%' and dbInfo['accept'] != '127.0.0.1': + pdata['dataAccess'] = '127.0.0.1' + pdata['address'] = dbInfo['accept'] + pdata['ps'] = dbInfo['ps'] + pdata['codeing'] = dbInfo['character'] + + result = self.sendPlugins('mysql', 'add_db', pdata) + rdata = json.loads(result['data']) + + if rdata['status']: + return True + err_msg = '数据库[{}]创建失败,{}'.format(dbInfo['name'], rdata['msg']) + self.state('databases', index, -1, err_msg) + self.error(err_msg) + return False + + # 数据库密码处理 + def mypass(self, act, root): + # conf_file = '/etc/my.cnf' + conf_file = self.getConf('mysql') + mw.execShell("sed -i '/user=root/d' {}".format(conf_file)) + mw.execShell("sed -i '/password=/d' {}".format(conf_file)) + if act: + mycnf = mw.readFile(conf_file) + src_dump = "[mysqldump]\n" + sub_dump = src_dump + "user=root\npassword=\"{}\"\n".format(root) + if not mycnf: + return False + mycnf = mycnf.replace(src_dump, sub_dump) + if len(mycnf) > 100: + mw.writeFile(conf_file, mycnf) + return True + return True + + def export_database(self, name, index): + self.write_speed('done', '正在导出数据库') + write_log("|-正在导出数据库{}...".format(name)) + conn = self.getMyConn() + result = conn.execute("show databases") + isError = self.isSqlError(result) + if isError: + err_msg = '数据库[{}]导出失败,{}!'.format(name, isError['msg']) + self.state('databases', index, -1, err_msg) + self.error(err_msg) + return None + + root = self.getDbConn('mysql', 'config').where( + 'id=?', (1,)).getField('mysql_root') + + backup_path = mw.getRootDir() + '/backup' + if not os.path.exists(backup_path): + os.makedirs(backup_path, 384) + + backup_name = backup_path + '/psync_import.sql.gz' + if os.path.exists(backup_name): + os.remove(backup_name) + + root_dir = mw.getServerDir() + '/mysql' + my_cnf = self.getConf('mysql') + cmd = root_dir + "/bin/mysqldump --defaults-file=" + my_cnf + " --default-character-set=" + \ + self.getDatabaseCharacter( + name) + " --force --opt \"" + name + "\" | gzip > " + backup_name + mw.execShell(cmd) + + self.mypass(False, root) + if not os.path.exists(backup_name) or os.path.getsize(backup_name) < 30: + if os.path.exists(backup_name): + os.remove(backup_name) + err_msg = '数据库[{}]导出失败!'.format(name) + self.state('databases', index, -1, err_msg) + self.error(err_msg) + write_log("失败") + return None + write_log("成功") + return backup_name + + def send_database(self, dbInfo, index): + # print(dbInfo) + # 创建远程库 + # if not self.create_database(dbInfo, index): + # return False + + self.create_database(dbInfo, index) + filename = self.export_database(dbInfo['name'], index) + if not filename: + return False - siteInfo['port'] = mw.M('domain').where( - 'pid=? and name=?', (pid, sites[i],)).getField('port') + db_dir = '/www/backup/database' + upload_file = db_dir + '/psync_import_{}.sql.gz'.format(dbInfo['name']) + d = self.send('/files/exec_shell', + {"shell": "rm -f " + upload_file, "path": "/www"}, 30) - siteInfo['domain'] = mw.M('domain').where( - 'pid=? and name!=?', (pid, sites[i])).field('name,port').select() + print(d) + if self.upload_file(filename, upload_file): - print(sites[i]) - print("dd:", mw.M('domain').where( - 'pid=? and name!=?', (pid, sites[i])).field('name,port').select()) + self.write_speed('done', '正在导入数据库') + write_log("|-正在导入数据库{}...".format(dbInfo['name'])) + print(filename) - if self.send_site(siteInfo, i): - self.state('sites', i, 2) - write_log("=" * 50) - print(sites) + self.state('databases', index, -1, "数据传输失败") + + def sync_database(self): + data = getCfgData() + databases = data['ready']['databases'] + for i in range(len(databases)): + try: + self.state('databases', i, 1) + db = databases[i] + + sp_msg = "|-迁移数据库: [{}]".format(db) + self.write_speed('action', sp_msg) + write_log(sp_msg) + dbInfo = self.getDbInfo(db) + dbInfo['accept'] = self.getDatabaseAccess(db) + dbInfo['character'] = self.getDatabaseCharacter(db) + print(dbInfo) + if self.send_database(dbInfo, i): + self.state('databases', i, 2) + write_log("=" * 50) + except: + self.error(mw.getTracebackInfo()) def run(self): # 开始迁移 + # self.upload_file( + # "/Users/midoks/Desktop/mwdev/backup/mysql-boost-5.7.39.tar.gz", "/tmp/mysql-boost-5.7.39.tar.gz") + # mw.CheckMyCnf() # self.sync_other() self.sync_site() - # self.sync_database() - # self.sync_ftp() + self.sync_database() # self.sync_path() - # self.write_speed('action', 'True') + self.write_speed('action', 'True') write_log('|-所有项目迁移完成!') +# 字节单位转换 +def toSize(size): + d = ('b', 'KB', 'MB', 'GB', 'TB') + s = d[0] + for b in d: + if size < 1024: + return ("%.2f" % size) + ' ' + b + size = size / 1024 + s = b + return ("%.2f" % size) + ' ' + b + + def getPluginName(): return 'migration_api' @@ -290,6 +696,9 @@ def checkArgs(data, ck=[]): def status(): + path = getServerDir() + '/config' + if not os.path.exists(path): + os.makedirs(path) return 'start' @@ -417,6 +826,8 @@ def write_log(log_str): log_file = getServerDir() + '/sync.log' f = open(log_file, 'ab+') log_str += "\n" + if __name__ == '__main__': + print(log_str) f.write(log_str.encode('utf-8')) f.close() return True @@ -424,6 +835,10 @@ def write_log(log_str): def bgProcessRun(): data = getCfgData() + + demo_url = 'http://127.0.0.1:7200' + demo_key = 'HfJNKGP5RPqGvhIOyrwpXG4A2fTjSh9B' + # api = classApi(demo_url, demo_key) api = classApi(data['url'], data['token']) api.run() return '' @@ -486,6 +901,7 @@ def getSpeed(): except: return mw.returnJson(False, '正在准备..') sync_info = self.get_sync_info(None) + print(sync_info) speed_info['all_total'] = sync_info['total'] speed_info['all_speed'] = sync_info['speed'] speed_info['total_time'] = speed_info['end_time'] - speed_info['time'] diff --git a/plugins/mysql/index.py b/plugins/mysql/index.py index f815fd21c..b786cf6d0 100755 --- a/plugins/mysql/index.py +++ b/plugins/mysql/index.py @@ -843,7 +843,6 @@ def setDbBackup(): return data[1] scDir = mw.getRunDir() + '/scripts/backup.py' - cmd = 'python3 ' + scDir + ' database ' + args['name'] + ' 3' os.system(cmd) return mw.returnJson(True, 'ok') @@ -904,10 +903,12 @@ def importDbExternal(): sock = getSocketFile() os.environ["MYSQL_PWD"] = pwd - mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p' + \ - pwd + ' ' + name + ' < ' + import_sql + mysql_cmd = getServerDir() + '/bin/mysql -S ' + sock + ' -uroot -p\"' + \ + pwd + '\" ' + name + ' < ' + import_sql + # print(mysql_cmd) rdata = mw.execShell(mysql_cmd) + # print(rdata) if ext != 'sql': os.remove(import_sql) diff --git a/scripts/backup.py b/scripts/backup.py index 89d122a42..4c526fa66 100755 --- a/scripts/backup.py +++ b/scripts/backup.py @@ -5,6 +5,7 @@ import sys import os +import re if sys.platform != 'darwin': os.chdir('/www/server/mdserver-web') @@ -50,7 +51,6 @@ class backupTools: mw.execShell(cmd) endDate = time.strftime('%Y/%m/%d %X', time.localtime()) - print(filename) if not os.path.exists(filename): log = "网站[" + name + "]备份失败!" @@ -83,6 +83,27 @@ class backupTools: if num < 1: break + def getConf(self, mtype='mysql'): + path = mw.getServerDir() + '/' + mtype + '/etc/my.cnf' + return path + + # 数据库密码处理 + def mypass(self, act, root): + conf_file = self.getConf('mysql') + mw.execShell("sed -i '/user=root/d' {}".format(conf_file)) + mw.execShell("sed -i '/password=/d' {}".format(conf_file)) + if act: + mycnf = mw.readFile(conf_file) + src_dump = "[mysqldump]\n" + sub_dump = src_dump + "user=root\npassword=\"{}\"\n".format(root) + if not mycnf: + return False + mycnf = mycnf.replace(src_dump, sub_dump) + if len(mycnf) > 100: + mw.writeFile(conf_file, mycnf) + return True + return True + def backupDatabase(self, name, count): db_path = mw.getServerDir() + '/mysql' db_name = 'mysql' @@ -104,17 +125,11 @@ class backupTools: filename = backup_path + "/db_" + name + "_" + \ time.strftime('%Y%m%d_%H%M%S', time.localtime()) + ".sql.gz" - import re mysql_root = mw.M('config').dbPos(db_path, db_name).where( "id=?", (1,)).getField('mysql_root') - mycnf = mw.readFile(db_path + '/etc/my.cnf') - rep = "\[mysqldump\]\nuser=root" - sea = "[mysqldump]\n" - subStr = sea + "user=root\npassword=" + mysql_root + "\n" - mycnf = mycnf.replace(sea, subStr) - if len(mycnf) > 100: - mw.writeFile(db_path + '/etc/my.cnf', mycnf) + my_cnf = self.getConf('mysql') + self.mypass(True, mysql_root) # mw.execShell(db_path + "/bin/mysqldump --opt --default-character-set=utf8 " + # name + " | gzip > " + filename) @@ -125,8 +140,10 @@ class backupTools: # mw.execShell(db_path + "/bin/mysqldump --single-transaction --quick --default-character-set=utf8 " + # name + " | gzip > " + filename) - mw.execShell(db_path + "/bin/mysqldump --force --opt --default-character-set=utf8 " + - name + " | gzip > " + filename) + cmd = db_path + "/bin/mysqldump --defaults-file=" + my_cnf + " --force --opt --default-character-set=utf8 " + \ + name + " | gzip > " + filename + # print(cmd) + mw.execShell(cmd) if not os.path.exists(filename): endDate = time.strftime('%Y/%m/%d %X', time.localtime()) @@ -136,10 +153,7 @@ class backupTools: "----------------------------------------------------------------------------") return - mycnf = mw.readFile(db_path + '/etc/my.cnf') - mycnf = mycnf.replace(subStr, sea) - if len(mycnf) > 100: - mw.writeFile(db_path + '/etc/my.cnf', mycnf) + self.mypass(False, mysql_root) endDate = time.strftime('%Y/%m/%d %X', time.localtime()) outTime = time.time() - startTime