| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| import datetime |
| import json |
| import os |
| import time |
| import sys |
| import concurrent.futures |
| import threading |
| import hashlib |
|
|
| if '/www/server/panel/class' not in sys.path: |
| sys.path.insert(0, '/www/server/panel/class') |
| if '/www/server/panel' not in sys.path: |
| sys.path.insert(0, '/www/server/panel') |
| import public |
| import panelMysql |
| import db_mysql |
| import database |
| import psutil |
| import ajax |
| from firewallModel.comModel import main as firewall_main |
| from safeModel.firewallModel import main as safe_firewall_main |
| from CloudStoraUpload import CloudStoraUpload |
|
|
|
|
| class main: |
| sys_config = public.M('config').where("id=1", ()).find() |
| setting_path='{}/data/whole_machine_backup_settings.json'.format(public.get_panel_path()) |
| if os.path.exists(setting_path): |
| sys_backup_path = json.loads(public.ReadFile(setting_path))['sys_backup_path'] |
| else: |
| sys_backup_path = '/www/backup/' |
| if sys_config and sys_config.get('backup_path'): |
| sys_backup_path = sys_config.get('backup_path') |
| sys_backup_path = sys_backup_path if sys_backup_path.endswith('/') else sys_backup_path + '/' |
| backup_path = '{}whole_machine_backup/'.format(sys_backup_path) |
| backup_log_path = '{}log/'.format(backup_path) |
| all_backup_config_path = os.path.join(public.get_panel_path(), 'config/whole_machine_backup.json') |
| time_str = public.format_date() |
| lock = None |
| executor = None |
| functions = [] |
| backup_config = {} |
| reduction_config = {} |
| backup_save_config = backup_path + '{}/backup.json' |
| id_config = None |
| backup_record = None |
| reduction_log_path = None |
| backup_task_data = None |
| logs_file = '{}whole_machine_backup.log'.format(backup_path) |
| status = None |
| error_num = 0 |
| access_num = 0 |
|
|
| def __init__(self): |
| if not os.path.exists(self.backup_path): |
| public.ExecShell("mkdir -p {}".format(self.backup_path)) |
| public.ExecShell("chmod -R 755 {}".format(self.backup_path)) |
| public.ExecShell("chown -R www:www {}".format(self.backup_path)) |
| if not os.path.exists(self.all_backup_config_path): |
| public.writeFile(self.all_backup_config_path, json.dumps({})) |
| self.config = json.loads(public.readFile(self.all_backup_config_path)) |
|
|
| def print_log(self, log: str): |
| time_str = time.strftime('%Y-%m-%d %H:%M:%S') |
| log = "{} $$ {}".format(time_str, log) |
| public.writeFile(self.logs_file, log + "\n", 'a+') |
|
|
| def write_config(self, id, conf): |
| self.config[id] = conf |
| public.writeFile(self.all_backup_config_path, json.dumps(self.config)) |
|
|
| def get_md5(self, path): |
| try: |
| if os.path.exists(path) and os.path.isfile(path): |
| return public.FileMd5(path) |
| return False |
| except: |
| return False |
|
|
| |
| |
| |
|
|
| |
|
|
| |
| def get_task_list(self, get=None): |
| try: |
| if not hasattr(get, 'page') or get.page == '': |
| get.page = 1 |
| if not hasattr(get, 'limit') or get.limit == '': |
| get.limit = 10 |
| get.page, get.limit = int(get.page), int(get.limit) |
| result = [] |
| ids = ['log'] |
| for k, v in self.config.items(): |
| info = {'id': k} |
| ids.append(k) |
| info.update(v) |
| info['backup_path'] = info['backup_path'] + '.tar.gz' |
| result.append(info) |
| for i in os.listdir(self.backup_path): |
| if os.path.isdir(os.path.join(self.backup_path, i)) and i not in ids: |
| public.ExecShell('rm -rf {}'.format(os.path.join(self.backup_path, i))) |
| result = sorted(result, key=lambda x: x['addtime'], reverse=True) |
| |
| data = public.get_page(len(result), get.page, get.limit) |
| data['data'] = result[get.page * get.limit - get.limit:get.page * get.limit] |
| return public.returnMsg(True, data) |
| except: |
| self.print_log(public.get_error_info()) |
| return public.returnMsg(False, '获取任务列表失败!') |
|
|
| |
| def get_task_info(self, get): |
| if not hasattr(get, 'id'): |
| return public.returnMsg(False, '参数错误,缺少参数id!') |
| if get.id not in self.config: |
| return public.returnMsg(False, '任务不存在!') |
| task_config_path = self.config[get.id]["task_config"] |
| try: |
| task_config = json.loads(public.readFile(task_config_path)) |
| if isinstance(task_config['backup_config'], str): |
| task_config['backup_config'] = json.loads(task_config['backup_config']) |
| if isinstance(task_config['reduction_config'], str): |
| task_config['reduction_config'] = json.loads(task_config['reduction_config']) |
| except: |
| return public.returnMsg(False, '任务配置文件读取失败!') |
| return public.returnMsg(True, task_config) |
|
|
| |
| def del_task(self, get): |
| if not hasattr(get, 'id'): |
| return public.returnMsg(False, '参数错误,缺少参数id!') |
| if get.id not in self.config: |
| return public.returnMsg(False, '任务不存在!') |
| if "task_id" in self.config[get.id]: |
| count = public.M('tasks').where("id=? nd status!='1'", (self.config[get.id]["task_id"],)).count() |
| if count: |
| return public.returnMsg(False, '任务正在执行中,请等待执行结束后再删除!') |
| del self.config[get.id] |
| public.ExecShell("rm -rf {}*".format(os.path.join(self.backup_path, get.id))) |
| public.ExecShell("rm -rf {}".format(os.path.join(self.backup_log_path, get.id + "_backup.log"))) |
| public.ExecShell("rm -rf {}".format(os.path.join(self.backup_log_path, get.id + "_reduction.log"))) |
| public.writeFile(self.all_backup_config_path, json.dumps(self.config)) |
| return public.returnMsg(True, '删除成功!') |
|
|
| |
| def get_backup_log(self, get): |
| if not hasattr(get, 'id'): |
| return public.returnMsg(False, '参数错误,缺少参数id!') |
| if get.id not in self.config: |
| return public.returnMsg(False, '任务不存在,请刷新后重试!!') |
| backup_log_path = self.config[get.id]["backup_log_path"] |
| if not os.path.exists(backup_log_path): |
| return public.returnMsg(False, '未检测到日志!') |
| log = public.readFile(backup_log_path) |
| if log: |
| try: |
| log = json.loads(log) |
| return public.returnMsg(True, log) |
| except: |
| pass |
| return public.returnMsg(False, "日志格式话出错!") |
|
|
| |
| def get_reduction_log(self, get): |
| if not hasattr(get, 'id'): |
| return public.returnMsg(False, '参数错误,缺少参数id!') |
| if get.id not in self.config: |
| return public.returnMsg(False, '任务不存在,请刷新后重试!') |
| reduction_log_path = self.config[get.id]["reduction_log_path"] |
| if not os.path.exists(reduction_log_path): |
| return public.returnMsg(False, '未检测到日志!') |
| log = public.readFile(reduction_log_path) |
| if log: |
| try: |
| log = json.loads(log) |
| return public.returnMsg(True, log) |
| except: |
| pass |
| return public.returnMsg(False, "日志格式话出错!") |
|
|
| |
| def get_data_list(self, get): |
| """ |
| 获取备份数据列表 |
| :param get: |
| """ |
| result = {} |
| |
| result["env_list"] = self.get_env_list() |
| |
| result["data_list"] = {} |
| result["data_list"]["site_list"] = self.get_site_list() |
| result["data_list"]["sql_list"] = self.get_sql_list() |
| result["data_list"]["ftp_list"] = self.get_ftp_list() |
| result["data_list"]["terminal_list"] = self.get_terminal_list() |
| result["data_list"]["crontab_list"] = self.get_crontab_list() |
| result["data_list"]['safety'] = { |
| "port_list": [{"name": "端口规则", "status": 1, "backup_status": 0, "reduction_status": 0}], |
| "ip_list": [{"name": "IP规则", "status": 1, "backup_status": 0, "reduction_status": 0}], |
| "port_redirect": [{"name": "端口转发", "status": 1, "backup_status": 0, "reduction_status": 0}], |
| "area_list": [{"name": "地区规则", "status": 1, "backup_status": 0, "reduction_status": 0}], |
| "ssh_config": [{"name": "ssh配置", "status": 1, "backup_status": 0, "reduction_status": 0}], |
| 'words': [{"name": "违规词检测-关键词", "status": 1, "backup_status": 0, "reduction_status": 0}], |
| } |
| |
| |
| return result |
|
|
| def get_site_list(self): |
| """ |
| 获取站点列表 |
| :return: dict |
| """ |
| |
| result = {'php': [], 'proxy': []} |
| |
| data = public.M('sites').field('name,project_type,id,ps').select() |
| if isinstance(data, str): |
| return {} |
| for i in data: |
| if i['project_type'].lower() not in result.keys(): |
| continue |
| result[i['project_type'].lower()].append({"name": i['name'], "status": 1, "backup_status": 0, "reduction_status": 0, "id": i['id'], 'ps': i['ps']}) |
| cont = [i for i, j in result.items() if not j] |
| [result.pop(i) for i in cont] |
| return result |
|
|
| def get_sql_list(self): |
| """ |
| 获取数据库列表 |
| :return: dict |
| """ |
| result = {} |
| data = public.M('databases').field('name,type,id').select() |
| result['mysql'] = [] |
| if isinstance(data, str): |
| return {} |
| for i in data: |
| if i['type'].lower() not in result: |
| continue |
| if i['type'].lower() in ['mysql']: |
| result[i['type'].lower()].append({"name": i['name'], "status": 1, "backup_status": 0, "reduction_status": 0, "id": i['id']}) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| return result |
|
|
| def get_ftp_list(self): |
| """ |
| 获取ftp列表 |
| :return: list |
| """ |
| result = [] |
| data = public.M('ftps').field('name,id').select() |
| if isinstance(data, str): |
| return [] |
| for i in data: |
| result.append({"name": i['name'], "status": 1, "backup_status": 0, "reduction_status": 0, "id": i['id']}) |
| return result |
|
|
| def get_env_list(self): |
| result = {} |
| |
| web_type = public.get_webserver() |
| if web_type == 'nginx': |
| web_setup = os.path.exists('/www/server/nginx') |
| web_version = public.readFile('/www/server/nginx/version.pl').strip() if web_setup else "" |
| elif web_type == 'apache': |
| web_setup = os.path.exists('/www/server/apache') |
| web_version = public.readFile('/www/server/apache/version.pl').strip() if web_setup else "" |
| else: |
| web_setup = False |
| web_version = "" |
| result[web_type] = [{"setup": web_setup, "name": web_version, "status": 1 if web_setup else 0, "backup_status": 0, "reduction_status": 0}] |
|
|
| |
| mysql_path = "/www/server/mysql" |
| mysql_setup = os.path.exists(mysql_path) |
| mysql_version = public.readFile(mysql_path + "/version.pl").strip() if mysql_setup else "" |
| result['mysql'] = [{"setup": mysql_setup, "name": mysql_version, "status": 1 if mysql_setup else 0, "backup_status": 0, "reduction_status": 0, "primitive_data": "0"}] |
|
|
| |
| ftp_path = "/www/server/pure-ftpd" |
| ftp_setup = os.path.exists(ftp_path) |
| ftp_version = public.readFile(ftp_path + "/version.pl").strip() if ftp_setup else "" |
| result['ftp'] = [{"setup": ftp_setup, "name": ftp_version, "status": 1 if ftp_setup else 0, "backup_status": 0, "reduction_status": 0}] |
|
|
| |
| php_path = "/www/server/php" |
| php_list = ['52', '53', '54', '55', '56', '70', '71', '72', '73', '74', '80', '81', '82', '83'] |
| for i in php_list: |
| if 'php' not in result: |
| result['php'] = [] |
| try: |
| int(i) |
| result['php'].append({"name": i, "status": 1 if os.path.exists('/www/server/php/{}/bin'.format(i)) else 0, "backup_status": 0, "reduction_status": 0, |
| 'setup': os.path.exists('/www/server/php/{}/bin'.format(i))}) |
| except: |
| pass |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| return result |
|
|
| def get_config_list(self): |
| result = {"alarm": [{"name": "面板告警", "status": 3, "backup_status": 0, "reduction_status": 0}], } |
| return result |
|
|
| def get_terminal_list(self): |
| result = [] |
| result.append({"name": "服务器列表", "status": 1, "backup_status": 0, "reduction_status": 0}) |
| result.append({"name": "常用命令", "status": 1, "backup_status": 0, "reduction_status": 0}) |
| return result |
|
|
| def get_crontab_list(self): |
| result = [] |
| result.append({"name": "计划任务列表", "status": 1, "backup_status": 0, "reduction_status": 0}) |
| return result |
|
|
| |
| |
| |
|
|
| def create_task(self, get): |
| """ |
| 创建备份任务 |
| :param get: |
| type: 1:备份 2还原 |
| id: 还原配置id |
| conf: 备份配置信息 |
| :return: |
| """ |
| if not hasattr(get, 'type'): |
| return public.returnMsg(False, '参数错误,缺少参数type!') |
| if not hasattr(get, 'id') and get.type == '2' and not hasattr(get, 'reduction_config'): |
| return public.returnMsg(False, '参数错误,缺少参数reduction_config或id!') |
| if get.type == '1' and not hasattr(get, 'backup_config'): |
| return public.returnMsg(False, '参数错误,缺少参数backup_config!') |
| if not hasattr(get, "backup_type") or get.backup_type == "": |
| get.backup_type = "整机备份" |
| if not hasattr(get, "next_exec_time") or get.next_exec_time == "": |
| get.next_exec_time = "0" |
| |
| |
| storage_type = get.storage_type if hasattr(get, 'storage_type') else 'local' |
| if get.type == '2' and storage_type !='local': |
| return public.returnMsg(False, '暂时不还原云存储文件!') |
|
|
| try: |
| |
| if get.type == '1': |
| name = "备份任务" |
| else: |
| name = "还原任务" |
|
|
| |
| task_data = public.M('tasks').where("name = ? AND status != ?", ("{}".format(name), "1")).find() |
| if task_data: |
| return public.returnMsg(False, '已有重复的任务了,请上一个备份任务执行完成后再进行添加新的备份任务!') |
|
|
| |
| get.type = get.type if hasattr(get, 'type') else '1' |
| get.backup_sql_time = int(get.backup_sql_time) if hasattr(get, 'backup_sql_time') else 0 |
|
|
| if int(get.type) == 1: |
| if get.next_exec_time not in [0, '0']: |
| exec_time=datetime.datetime.fromtimestamp(int(get.next_exec_time)).strftime("%Y-%m-%d %H:%M:%S") |
| else: |
| exec_time="暂未执行" |
| |
| get.backup_config = get.backup_config if isinstance(get.backup_config, str) else json.dumps(get.backup_config) |
|
|
| |
| get.id = public.GetRandomString(16) |
|
|
| |
| task_config_path = os.path.join(self.backup_path, get.id, "task_config.json") |
| reduction_task_config_path = os.path.join(self.backup_path, get.id + "_reduction.json") |
| storage_backup_path="" |
| if storage_type !='local': |
| name="{}.tar.gz".format(get.id) |
| cloud_name=get.storage_type |
| import CloudStoraUpload |
| c = CloudStoraUpload.CloudStoraUpload() |
| c.run(cloud_name) |
| url = '' |
| backup_path = c.obj.backup_path |
| storage_backup_path = os.path.join(backup_path, "whole_machine_backup",name) |
|
|
| |
| |
| conf = { |
| "backup_sql_time": get.backup_sql_time, |
| "addtime": time.strftime('%Y-%m-%d %H:%M:%S'), |
| "backup_path": os.path.join(self.backup_path, get.id), |
| "backup_log_path": os.path.join(self.backup_log_path, get.id + "_backup.log"), |
| "reduction_log_path": os.path.join(self.backup_log_path, get.id + "_reduction.log"), |
| "status": 0, |
| "task_config": task_config_path, |
| "reduction_task_config_path": reduction_task_config_path, |
| "exec_time": exec_time, |
| "backup_type": get.backup_type, |
| "name": get.get('name', get.backup_type), |
| "storage_type":storage_type, |
| "storage_backup_path":storage_backup_path |
| } |
| |
| if not os.path.exists(os.path.join(self.backup_path, get.id)): |
| public.ExecShell("mkdir -p {}".format(os.path.join(self.backup_path, get.id))) |
|
|
| |
| task_config = { |
| "backup_config": get.backup_config, |
| "reduction_config": {} |
| } |
| public.writeFile(task_config_path, json.dumps(task_config)) |
|
|
| |
| self.write_config(get.id, conf) |
|
|
| |
| if get.next_exec_time not in [0, '0']: |
| data = { |
| "name": 'whole_machine_backup', |
| "title": '面板数据备份', |
| "type": "1", |
| "time": str(int(get.next_exec_time) + 10), |
| "fun": 'create_queue', |
| "args": {"id": get.id, "type": 1}, |
| "model_index": "panel" |
| } |
| public.set_tasks_run(data) |
| else: |
| |
| self.create_queue(public.to_dict_obj({"id": get.id, "type": 1})) |
|
|
| elif int(get.type) == 2: |
| |
| if get.id not in self.config: |
| return public.returnMsg(False, '还原配置不存在,请刷新后重试!') |
|
|
| |
| reduction_task_config_path = os.path.join(self.backup_path, get.id + "_reduction.json") |
|
|
| |
| reduction_config = get.reduction_config |
| task_config = {"reduction_config": reduction_config} |
| public.writeFile(reduction_task_config_path, json.dumps(task_config)) |
|
|
| |
| self.create_queue(public.to_dict_obj({"id": get.id, "type": 2})) |
|
|
| return public.returnMsg(True, '添加成功!') |
|
|
| except: |
| |
| self.print_log(public.get_error_info()) |
| return public.returnMsg(False, '添加任务报错了!') |
|
|
| def check_plugins(self, get): |
| import PluginLoader |
| """ |
| 检查指定目录下是否存在某些插件目录,并判断对应存储是否安装 |
| |
| :param plugin_path: 插件目录的路径,例如 "/www/server/panel/plugin" |
| :return: 一个字典,包含每个插件的安装状态 |
| """ |
| import os |
|
|
| plugin_path = "{}/plugin".format(public.get_panel_path()) |
| |
| plugins = ["alioss", "txcos", "ftp", "qiniu","webdav"] |
|
|
| |
| result = {} |
|
|
| |
| for plugin in plugins: |
| plugin_dir = os.path.join(plugin_path, plugin) |
|
|
| |
| result[plugin] = { |
| "install": os.path.exists(plugin_dir), |
| "config": False |
| } |
|
|
| |
| if result[plugin]["install"]: |
| try: |
| |
| get.path = "/" |
| if plugin == "webdav": |
| res = PluginLoader.plugin_run(plugin, "list_files", get) |
| if not "status" in res: |
| print(res) |
| result[plugin]["config"] = True |
| else: |
| res = PluginLoader.plugin_run(plugin, "get_list", get) |
| if "list" in res and "list": |
| result[plugin]["config"] = True |
| |
| |
| |
| except Exception as e: |
| |
| result[plugin]["config"] = False |
|
|
| return public.returnMsg(True, result) |
|
|
| def delete_account(self, get): |
| storage_type=get.storage_type |
| panel_path=public.get_panel_path() |
| plugin_path = "{}/plugin".format(panel_path) |
| config_path = os.path.join(plugin_path, storage_type,"config.conf") |
| aes_status_path = os.path.join(plugin_path, storage_type,"aes_status") |
| data_path=os.path.join("{}/data".format(panel_path),"{}AS.conf".format(storage_type)) |
| |
| |
| public.ExecShell("rm -rf {}".format(config_path)) |
| public.ExecShell("rm -rf {}".format(aes_status_path)) |
| public.ExecShell("rm -rf {}".format(data_path)) |
| return public.returnMsg(True, "删除账号成功!") |
|
|
|
|
| def backup_download(self, get): |
| if not hasattr(get, 'backup_path') or not hasattr(get, 'storage_type'): |
| return public.returnMsg(False, '请传入backup_path!') |
| |
| plugin_status = self.check_plugins(get)["msg"] |
| storage_type = get.storage_type |
| if storage_type not in ["alioss", "txcos", "ftp", "qiniu", "webdav","local"]: |
| return public.returnMsg(False, "不支持该插件:{}".format(storage_type)) |
| if storage_type in plugin_status: |
| if not plugin_status[storage_type]["install"]: |
| return public.returnMsg(False, "请先安装{}存储插件!".format(storage_type)) |
| if not plugin_status[storage_type]["config"]: |
| return public.returnMsg(False, "{}存储插件未配置,请先配置!".format(storage_type)) |
|
|
| backup_path=get.backup_path |
| if get.storage_type=="webdav" or get.storage_type=="local" or get.storage_type=="ftp": |
| if get.storage_type=="webdav": |
| import sys |
| if '/www/server/panel/plugin/webdav' not in sys.path: |
| sys.path.insert(0, '/www/server/panel/plugin/webdav') |
| try: |
| from webdav_main import webdav_main as webdav |
| |
| |
| download_path=os.path.join(webdav().default_backup_path , "whole_machine_backup",os.path.basename(backup_path)) |
| local_path = os.path.join("/tmp", os.path.basename(backup_path)) |
| webdav().client.download_file(from_path=download_path, to_path=local_path) |
| path=local_path |
| except Exception as e: |
| if "could not be found in the server" in str(e): |
| return public.returnMsg(False, '在云存储中未发现该文件!') |
| return public.returnMsg(False, '请先安装webdav存储插件!') |
| elif get.storage_type=="ftp": |
| import sys |
| if '/www/server/panel/plugin/ftp' not in sys.path: |
| sys.path.insert(0, '/www/server/panel/plugin/ftp') |
| try: |
| from ftp_main import ftp_main as ftp |
| |
| |
| ftp_backup_path=ftp().get_config(get)['backup_path'] |
| download_path=os.path.join(ftp_backup_path , "whole_machine_backup",os.path.basename(backup_path)) |
| local_path = os.path.join("/tmp", os.path.basename(backup_path)) |
| ftp().client.generate_download_url(download_path) |
| path=local_path |
| except: |
| import traceback |
| print(traceback.format_exc()) |
| return public.returnMsg(False, '请先安装ftp存储插件!') |
| else: |
| path = get.backup_path |
| if os.path.exists(path): |
| return {'status': True, 'is_loacl': True, 'path': path} |
| return public.returnMsg(False, '文件不存在!') |
| else: |
| name=os.path.basename(backup_path) |
| cloud_name=get.storage_type |
| import CloudStoraUpload |
| c = CloudStoraUpload.CloudStoraUpload() |
| c.run(cloud_name) |
| url = '' |
| backup_path = c.obj.backup_path |
| path = os.path.join(backup_path, "whole_machine_backup") |
| data = c.obj.get_list(path) |
| for i in data['list']: |
| print(i) |
| if i['name'] == name: |
| url = i['download'] |
| if url == '': |
| return public.returnMsg(False, '在云存储中未发现该文件!') |
| return {'status': True, 'is_loacl': False, 'path': url} |
|
|
| |
| def get_sys_backup_path_config(self,get=None): |
| setting_path='{}/data/whole_machine_backup_settings.json'.format(public.get_panel_path()) |
| try: |
| with open(setting_path, 'r') as f: |
| settings = json.load(f) |
| except: |
| settings = {'sys_backup_path': self.sys_backup_path} |
| with open(setting_path, 'w') as f: |
| json.dump(settings, f) |
| sys_backup_path = settings.get('sys_backup_path', self.sys_backup_path) |
| return public.returnMsg(True,sys_backup_path) |
|
|
| def set_sys_backup_path_config(self, get): |
| setting_path='{}/data/whole_machine_backup_settings.json'.format(public.get_panel_path()) |
| sys_backup_path = get.sys_backup_path if get.sys_backup_path.endswith('/') else get.sys_backup_path + '/' |
| |
| if not os.path.isabs(sys_backup_path): |
| return public.returnMsg(False, "请输入正确的目录路径!") |
| settings = { |
| 'sys_backup_path': sys_backup_path |
| } |
| with open(setting_path, 'w') as f: |
| json.dump(settings, f) |
| return public.returnMsg(True, "设置成功!") |
|
|
|
|
| |
| |
| |
| |
| def backup(self, id): |
| """ |
| 备份 |
| :param id: |
| :return: |
| """ |
| try: |
| if not isinstance(id, str): |
| id = id['id'] |
| |
| |
| if id not in self.config.keys(): |
| return public.returnMsg(False, '任务不存在!') |
| self.backup_save_config = self.backup_save_config.format(id) |
| self.backup_log_path = self.config[id]["backup_log_path"] |
| conf = self.config[id] |
| conf["status"] = -1 |
| self.status = 1 |
| conf["exec_time"] = time.strftime('%Y-%m-%d %H:%M:%S') |
| self.write_config(id, conf) |
| backup_path = self.backup_path |
| self.backup_path = conf["backup_path"] |
| if not os.path.exists(self.backup_path): |
| public.ExecShell('mkdir -p {}'.format(os.path.basename(self.backup_path))) |
| if not os.path.exists(os.path.join(self.backup_path, "backup")): |
| public.ExecShell('mkdir -p {}'.format(os.path.join(self.backup_path, "backup"))) |
| if not os.path.exists(os.path.dirname(self.backup_log_path)): |
| public.ExecShell('mkdir -p {}'.format(os.path.dirname(self.backup_log_path))) |
| |
| self.backup_config = json.loads(public.readFile(conf["task_config"]))["backup_config"] |
| self.backup_config = json.loads(self.backup_config) |
| if not os.path.exists(self.backup_log_path): |
| public.writeFile(self.backup_log_path, json.dumps(self.backup_config)) |
| else: |
| try: |
| self.backup_config = json.loads(public.readFile(self.backup_log_path)) |
| except: |
| pass |
| |
| |
| self.backup_env(self.backup_config) |
| |
| self.backup_data(self.backup_config) |
| |
| |
| |
| conf["status"] = self.status |
| conf['error_num'] = self.error_num |
| conf['access_num'] = self.access_num |
| conf_path = os.path.join(conf['backup_path'], id) |
| public.writeFile(conf_path, json.dumps({id: conf})) |
| public.ExecShell('cp {} {}'.format(self.backup_log_path, conf['backup_path'])) |
| public.ExecShell('cp {} {}'.format(os.path.join(conf['backup_path'], 'backup.json'), os.path.join(backup_path, id + '_backup.json'))) |
| |
| |
| |
| self.print_log(self.backup_path) |
| tar_gz_filename ="{}.tar.gz".format(self.backup_path) |
| public.ExecShell(f'tar -zcvf {tar_gz_filename} -C {self.backup_path} .') |
| self.print_log(f"->>>压缩备份文件完成:{tar_gz_filename}") |
| |
| |
| storage_type = conf.get("storage_type", "local") |
| cloud_backup_path = tar_gz_filename |
| |
| if storage_type != "local" and os.path.exists(tar_gz_filename): |
| _cloud_name = { |
| "tianyiyun": "天翼云cos", |
| "webdav": "webdav存储", |
| "minio": "minio存储", |
| "dogecloud": "多吉云COS", |
| } |
| print(333333333333333) |
| if storage_type in ["tianyiyun","webdav","minio","dogecloud"]: |
| cloud_name_cn = _cloud_name.get(storage_type, storage_type) |
| from CloudStoraUpload import CloudStoraUpload |
| _cloud_new = CloudStoraUpload() |
| _cloud = _cloud_new.run(storage_type) |
| if _cloud is False: |
| return False |
| self.print_log("->>>正在上传文件{}到{},请稍候...".format(tar_gz_filename,cloud_name_cn)) |
| try: |
| backup_path = _cloud_new.backup_path |
| if not backup_path.endswith('/'): |
| backup_path += '/' |
| upload_path = os.path.join(backup_path, "whole_machine_backup", os.path.basename(tar_gz_filename)) |
| self.print_log(tar_gz_filename) |
| self.print_log(upload_path) |
| if _cloud.upload_file(tar_gz_filename, upload_path): |
| self.print_log(f"->>>文件已成功上传到云存储:{cloud_name_cn}") |
| public.ExecShell('rm -rf {}'.format(tar_gz_filename)) |
| self.print_log('删除本地文件{}'.format(tar_gz_filename)) |
| |
| else: |
| self.print_log(f"->>>上传到{cloud_name_cn}失败") |
| except Exception as e: |
| self.print_log(f"->>>上传到{cloud_name_cn}时发生错误: {str(e)}") |
| else: |
| print(storage_type) |
| from CloudStoraUpload import CloudStoraUpload |
| _cloud = CloudStoraUpload() |
| _cloud.run(storage_type) |
| cloud_name_cn = _cloud.obj._title |
| if not _cloud.obj: |
| return False |
| self.print_log("->>>正在上传文件{}到{},请稍候...".format(tar_gz_filename,cloud_name_cn)) |
| try: |
| backup_path = _cloud.obj.backup_path |
| if not backup_path.endswith('/'): |
| backup_path += '/' |
| upload_path = os.path.join(backup_path, "whole_machine_backup", os.path.basename(tar_gz_filename)) |
| print(upload_path) |
| print((tar_gz_filename)) |
| if _cloud.cloud_upload_file(tar_gz_filename, upload_path): |
| self.print_log(f"->>>已成功上传到{cloud_name_cn}") |
| public.ExecShell('rm -rf {}'.format(tar_gz_filename)) |
| self.print_log('删除本地文件{}'.format(tar_gz_filename)) |
| |
| else: |
| self.print_log(f"->>>上传到{cloud_name_cn}失败") |
| except Exception as e: |
| self.print_log(f"->>>上传到{cloud_name_cn}时发生错误: {str(e)}") |
| |
| |
|
|
| public.ExecShell('rm -rf {}'.format(self.backup_path)) |
| self.write_config(id, conf) |
| return public.returnMsg(True, '备份完成!') |
| except: |
| print(public.get_error_info()) |
| return public.returnMsg(False, '备份失败!') |
| |
|
|
| |
| def change_backup_status1(self, block, name="", son_name="", status_name="", status=0, sec_name='', ): |
| |
| pass |
|
|
| def change_backup_status(self, block, name="", son_name="", status_name="", status=0, sec_name='', msg=''): |
| if status == 2: |
| self.status = 2 |
| self.error_num += 1 |
| if status == 1: |
| self.access_num += 1 |
| if sec_name != '': |
| for i in range(len(self.backup_config[block][name][son_name])): |
| if self.backup_config[block][name][son_name][i]['name'] == sec_name: |
| self.backup_config[block][name][son_name][i][status_name] = status |
| if status_name == 'backup_status': |
| if status == 1: |
| self.backup_config[block][name][son_name][i]['status'] = 1 |
| else: |
| self.backup_config[block][name][son_name][i]['status'] = 0 |
| if msg != "": |
| self.backup_config[block][name][son_name][i]['msg'] = msg |
| elif son_name != "": |
| for i in range(len(self.backup_config[block][name])): |
| if self.backup_config[block][name][i]['name'] == son_name: |
| self.backup_config[block][name][i][status_name] = status |
| if status_name == 'backup_status': |
| if status == 1: |
| self.backup_config[block][name][i]['status'] = 1 |
| else: |
| self.backup_config[block][name][i]['status'] = 0 |
| if msg != "": |
| self.backup_config[block][name][i]['msg'] = msg |
| else: |
| self.backup_config[block][status_name] = status |
| if status_name == 'backup_status': |
| if status == 1: |
| self.backup_config[block]['status'] = 1 |
| else: |
| self.backup_config[block]['status'] = 0 |
| if msg != "": |
| self.backup_config[block]['msg'] = msg |
| public.writeFile(self.backup_log_path, json.dumps(self.backup_config)) |
|
|
| def generate_md5(self, input_string): |
| |
| md5_hash = hashlib.md5() |
|
|
| |
| md5_hash.update(input_string.encode()) |
|
|
| |
| md5_hex = md5_hash.hexdigest() |
|
|
| return md5_hex |
|
|
| |
| def copy_file(self, path): |
| if not os.path.exists(path): |
| return False |
| md5_name = self.generate_md5(path) |
| save_path = os.path.join(self.backup_path, "backup", md5_name) |
| if os.path.exists(save_path): |
| return save_path |
| if os.path.isdir(path): |
| public.ExecShell('tar -zcvf {} -C {} .'.format(save_path, path)) |
| if os.path.isfile(path): |
| public.ExecShell('tar -zcvf {} -C {} {}'.format(save_path, os.path.dirname(path), os.path.basename(path))) |
| time.sleep(0.01) |
| if os.path.exists(save_path): |
| return save_path |
| else: |
| return False |
|
|
| def write_id_config(self, block, name="", son_name="", config={}, sec_name=''): |
| if self.id_config is None: |
| if not os.path.exists(self.backup_save_config): |
| public.writeFile(self.backup_save_config, json.dumps({})) |
| print(self.backup_save_config) |
| self.id_config = json.loads(public.readFile(self.backup_save_config)) |
| if sec_name != "": |
| if block not in self.id_config: |
| self.id_config[block] = {} |
| if name not in self.id_config[block]: |
| self.id_config[block][name] = {} |
| if son_name not in self.id_config[block][name]: |
| self.id_config[block][name][son_name] = {} |
| self.id_config[block][name][son_name][sec_name] = config |
| elif son_name != "": |
| if block not in self.id_config: |
| self.id_config[block] = {} |
| if name not in self.id_config[block]: |
| self.id_config[block][name] = {} |
| self.id_config[block][name][son_name] = config |
| elif name != "": |
| if block not in self.id_config: |
| self.id_config[block] = {} |
| self.id_config[block][name] = config |
| else: |
| self.id_config[block] = config |
| public.writeFile(self.backup_save_config, json.dumps(self.id_config)) |
|
|
| def uncopy_file(self, path, to_path, isfile=True, md5=False, unbak=False): |
| if not os.path.exists(path) and isfile: |
| return False |
| if os.path.exists(to_path): |
| if not unbak: |
| if os.path.exists(to_path + '_bak'): |
| public.ExecShell('rm -rf {}'.format(to_path + '_bak')) |
| public.ExecShell('mv {} {}'.format(to_path, to_path + '_bak')) |
|
|
| public.ExecShell('rm -rf {}'.format(to_path)) |
| if isfile: |
| public.ExecShell('tar -zxvf {} -C {} --overwrite'.format(path, os.path.dirname(to_path))) |
| else: |
| if not isfile: |
| public.ExecShell('mkdir -p {}'.format(to_path)) |
| public.ExecShell('tar -zxvf {} -C {} --overwrite'.format(path, to_path)) |
| time.sleep(0.01) |
| if os.path.exists(to_path): |
| if md5 and isfile: |
| if md5 == self.get_md5(to_path): |
| self.print_log('文件MD5比对成功') |
| return True |
| else: |
| self.print_log('文件md5比对失败') |
| return False |
| return True |
| else: |
| res, i_flag = self.check_copy_error(to_path) |
| if res: |
| if isfile: |
| public.ExecShell('tar -zxvf {} -C {} --overwrite'.format(path, to_path)) |
| else: |
| public.ExecShell('tar -zxvf {} -C {} --overwrite'.format(path, os.path.basename(to_path))) |
| time.sleep(0.01) |
| if i_flag: |
| public.ExecShell('chattr +i {}'.format(to_path)) |
| if os.path.exists(to_path): |
| if md5 and isfile: |
| if md5 == self.get_md5(to_path): |
| self.print_log('文件MD5比对成功') |
| return True |
| else: |
| self.print_log('文件md5比对失败') |
| return False |
| return True |
| return False |
|
|
| def check_copy_error(self, path): |
| |
| i_flag = False |
| disk_status = psutil.disk_usage('/') |
| if disk_status.used / disk_status.total >= 0.99: |
| self.print_log('磁盘空间不足') |
| return False, i_flag |
| if not os.path.exists(path): |
| |
| public.ExecShell('mkdir -p {}'.format(path)) |
| time.sleep(0.01) |
| if os.path.exists(path): |
| return True, i_flag |
| |
| if not os.access(path, os.W_OK): |
| self.print_log('文件无法写入,尝试修复') |
| public.ExecShell('chmod 777 {}'.format(path)) |
| public.ExecShell('chattr -i {}'.format(path)) |
| if not os.access(path, os.W_OK): |
| self.print_log('文件无法写入,无法修复') |
| return False, i_flag |
| else: |
| i_flag = True, i_flag |
| self.print_log('文件修复成功') |
| return True, i_flag |
| return False, i_flag |
| |
| |
| |
| |
| |
|
|
| def backup_env(self, conf): |
| env_conf = conf["env_list"] |
| connect = { |
| "php": self.backup_php, |
| "mysql": self.backup_mysql, |
| "mongo": self.backup_mongo, |
| "redis": self.backup_redis, |
| "pgsql": self.backup_pgsql, |
| "nginx": self.backup_nginx, |
| "apache": self.backup_apache, |
| "ftp": self.backup_ftp, |
| } |
| for k, v in env_conf.items(): |
| if not isinstance(v, list): |
| continue |
| for i in v: |
| if i['status'] in [1, -1, 2]: |
| connect[k](i) |
| else: |
| if i['name'] and i["status"] != 3: |
| self.change_backup_status("env_list", k, i["name"], "backup_status", 4, msg="未备份".format(i["name"])) |
|
|
| def backup_php(self, conf): |
| try: |
| self.change_backup_status("env_list", "php", conf["name"], "backup_status", -1, msg="开始备份php{}环境".format(conf["name"])) |
| php_verison = conf["name"] |
| flag = 1 |
| self.print_log("->>>开始获取php{}扩展列表".format(php_verison)) |
| res = public.ExecShell("/www/server/php/{}/bin/php -m".format(php_verison))[0] |
| php_development = res.split("\n") |
| |
| if len(php_development) > 1: |
| php_development = php_development[1:] |
| php_development = [i.strip() for i in php_development if i.strip() and '[' not in i] |
| else: |
| php_development = [] |
| |
| if 'swoole' in php_development: |
| res = public.ExecShell("/www/server/php/{}/bin/php --ri swoole | grep Version | awk '{{print $3}}'".format(php_verison))[0] |
| try: |
| index = php_development.index('swoole') |
| php_development[index] = 'swoole{}'.format(res.strip()[0] if res.strip()[0] in ['4', '5'] else res.strip()[0]) |
| except: |
| pass |
| |
| self.print_log("获取php{}扩展列表完成".format(php_verison)) |
|
|
| |
| self.print_log("开始备份php{}配置文件".format(php_verison)) |
| php_ini = "/www/server/php/{}/etc/php.ini".format(php_verison) |
| res = self.copy_file(php_ini) |
| if not res: |
| self.print_log("备份php{}配置文件失败".format(php_verison)) |
| self.change_backup_status("env_list", "php", conf["name"], "backup_status", 2, msg="备份php{}配置文件失败".format(php_verison)) |
| flag = 2 |
| php_ini_md5 = self.get_md5(php_ini) |
| php_ini_name = res |
| php_fpm_path = "/www/server/php/{}/etc/php-fpm.conf".format(php_verison) |
| res = self.copy_file(php_fpm_path) |
| if not res: |
| self.print_log("备份php{}配置文件失败".format(php_verison)) |
| self.change_backup_status("env_list", "php", conf["name"], "backup_status", 2, msg="备份php{}配置文件失败".format(php_verison)) |
| flag = 2 |
| php_fpm_md5 = self.get_md5(php_fpm_path) |
| php_fpm_name = res |
| |
| self.print_log("备份php{}配置文件完成".format(php_verison)) |
| words_path = "/www/server/panel/config/thesaurus.json" |
| wrods_data = None |
| words_data_md5 = None |
| if os.path.exists(words_path): |
| wrods_data = self.copy_file(words_path) |
| words_data_md5 = self.get_md5(words_path) |
| self.print_log("备份php{}关键词完成".format(php_verison)) |
| config = { |
| "php_development": php_development, |
| "php_ini": php_ini_name, |
| "php_fpm": php_fpm_name, |
| "wrods_data": wrods_data, |
| "php_ini_md5": php_ini_md5, |
| "php_fpm_md5": php_fpm_md5, |
| "words_data_md5": words_data_md5, |
| } |
| self.write_id_config("env_list", "php", conf["name"], config) |
| self.change_backup_status("env_list", "php", conf["name"], "backup_status", flag, msg="备份php{}完成".format(php_verison)) |
| self.print_log("->>>备份php{}完成".format(php_verison)) |
| except: |
| self.print_log("备份php{}出错".format(php_verison)) |
| self.print_log(public.get_error_info()) |
| self.change_backup_status("env_list", "php", conf["name"], "backup_status", 2, msg="备份php{}出错,程序出错".format(php_verison)) |
|
|
| def backup_mysql(self, conf): |
| try: |
| self.print_log("->>>开始备份mysql") |
| flag = 1 |
| mysql_data = None |
| mysql_conf = None |
| mysql_version = None |
| if not conf['setup']: |
| self.print_log("mysql未安装") |
| self.change_backup_status("env_list", "mysql", conf["name"], "backup_status", 2, msg="mysql未安装") |
| flag = 2 |
| else: |
| self.print_log("开始备份mysql{}版本".format(conf["name"])) |
| mysql_version = conf["name"] |
| self.print_log("开始备份mysql{}配置文件".format(mysql_version)) |
| mysql_conf = "/etc/my.cnf" |
| res = self.copy_file(mysql_conf) |
| if not res: |
| self.print_log("备份mysql{}配置文件失败".format(mysql_version)) |
| flag = 2 |
| else: |
| mysql_conf = res |
| if int(conf.get("primitive_data", 0)) == 1: |
| self.print_log("开始备份mysql{}数据文件".format(mysql_version)) |
| mysql_data = public.get_mysql_info()['datadir'] |
| res = self.copy_file(mysql_data) |
| if not res: |
| self.print_log("备份mysql{}数据文件失败".format(mysql_version)) |
| flag = 2 |
| else: |
| mysql_data = res |
| version = mysql_version |
| mysql_conf_md5 = self.get_md5("/etc/my.cnf") |
| config = { |
| "version": version, |
| "mysql_conf": mysql_conf, |
| "mysql_data": mysql_data, |
| "mysql_conf_md5": mysql_conf_md5, |
| } |
| self.write_id_config("env_list", "mysql", config=config) |
| self.change_backup_status("env_list", "mysql", son_name=conf["name"], status_name="backup_status", status=flag, msg="备份mysql完成") |
| self.print_log("->>>备份mysql完成") |
| except: |
| self.print_log("备份mysql出错") |
| self.print_log(public.get_error_info()) |
| self.change_backup_status("env_list", "mysql", conf["name"], "backup_status", 2, msg="备份mysql出错,程序出错") |
|
|
| def backup_mongo(self, conf): |
| try: |
| self.print_log("->>> 开始备份mongo") |
| flag = 1 |
| mongo_conf = None |
| mongo_version = None |
| mongo_conf_md5 = None |
| if not conf['setup']: |
| self.print_log("mongo未安装") |
| self.change_backup_status("env_list", "mongo", conf["name"], "backup_status", 2, msg="mongo未安装") |
| flag = 2 |
| else: |
| self.print_log("备份mongo{}版本".format(conf["name"])) |
| mongo_version = conf["name"] |
| self.print_log("备份mongo{}配置文件".format(mongo_version)) |
| mongo_conf = "/www/server/mongodb/config.conf" |
| mongo_conf_md5 = self.get_md5(mongo_conf) |
| res = self.copy_file(mongo_conf) |
| if not res: |
| self.print_log("备份mongo{}配置文件失败".format(mongo_version)) |
| flag = 2 |
| else: |
| mongo_conf = res |
| version = mongo_version |
| mongo_conf = mongo_conf |
| config = { |
| "version": version, |
| "mongo_conf": mongo_conf, |
| "mongo_conf_md5": mongo_conf_md5, |
| } |
| self.write_id_config("env_list", "mongo", config=config) |
| self.change_backup_status("env_list", "mongo", conf['name'], status_name="backup_status", status=flag, msg="备份mongo完成") |
| self.print_log("->>>备份mongo完成") |
| except: |
| self.print_log("备份mongo出错") |
| self.print_log(public.get_error_info()) |
| self.change_backup_status("env_list", "mongo", conf["name"], "backup_status", 2, msg="备份mongo出错,程序出错") |
|
|
| def backup_redis(self, conf): |
| try: |
| self.print_log("->>> 开始备份redis") |
| flag = 1 |
| redis_conf = None |
| redis_version = None |
| if not conf['setup']: |
| self.print_log("redis未安装") |
| self.change_backup_status("env_list", "redis", conf['name'], status_name="backup_status", status=2, msg="redis未安装") |
| flag = 2 |
| else: |
| self.print_log("备份redis{}版本".format(conf["name"])) |
| redis_version = conf["name"] |
| self.print_log("备份redis{}配置文件".format(redis_version)) |
| redis_conf = "/www/server/redis/redis.conf" |
| res = self.copy_file(redis_conf) |
| if not res: |
| self.print_log("备份redis{}配置文件失败".format(redis_version)) |
| flag = 2 |
| else: |
| redis_conf = res |
| version = redis_version |
| redis_conf = redis_conf |
| redis_conf_md5 = self.get_md5(redis_conf) |
| config = { |
| "version": version, |
| "redis_conf": redis_conf, |
| "redis_conf_md5": redis_conf_md5, |
| } |
| self.write_id_config("env_list", "redis", config=config) |
| self.change_backup_status("env_list", "redis", conf['name'], status_name="backup_status", status=flag, msg="备份redis完成") |
| self.print_log("->>>备份redis完成") |
| except: |
| self.print_log("备份redis出错") |
| print(public.get_error_info()) |
| self.change_backup_status("env_list", "redis", conf['name'], status_name="backup_status", status=2, msg="备份redis出错,程序出错") |
|
|
| def backup_pgsql(self, conf): |
| try: |
| self.print_log("->>> 开始备份pgsql") |
| flag = 1 |
| pgsql_conf = None |
| pgsql_version = None |
| client_conf = None |
| if not conf['setup']: |
| self.print_log("pgsql未安装") |
| self.change_backup_status("env_list", "pgsql", conf["name"], "backup_status", 2, msg="pgsql未安装") |
| flag = 2 |
| else: |
| self.print_log("备份pgsql{}版本".format(conf["name"])) |
| pgsql_version = conf["name"] |
| self.print_log("备份pgsql{}配置文件".format(pgsql_version)) |
| pgsql_conf = "/www/server/pgsql/data/postgresql.conf" |
| res = self.copy_file(pgsql_conf) |
| if not res: |
| self.print_log("备份pgsql{}主配置文件失败".format(pgsql_version)) |
| flag = 2 |
| else: |
| pgsql_conf = res |
| self.print_log("备份pgsql{}客户端配置文件".format(pgsql_version)) |
| client_conf_path = "/www/server/pgsql/data/pg_hba.conf" |
| res = self.copy_file(client_conf_path) |
| if not res: |
| self.print_log("备份pgsql{}客户端配置文件失败".format(pgsql_version)) |
| flag = 2 |
| else: |
| client_conf = res |
| version = pgsql_version |
| pgsql_conf = pgsql_conf |
| client_conf = client_conf |
| pgsql_conf_md5 = self.get_md5(pgsql_conf) |
| client_conf_md5 = self.get_md5(client_conf) |
| config = { |
| "version": version, |
| "pgsql_conf": pgsql_conf, |
| "client_conf": client_conf, |
| "pgsql_conf_md5": pgsql_conf_md5, |
| "client_conf_md5": client_conf_md5, |
| } |
| self.write_id_config("env_list", "pgsql", config=config) |
| self.change_backup_status("env_list", "pgsql", conf['name'], status_name="backup_status", status=flag, msg="备份pgsql完成") |
| self.print_log("->>>备份pgsql完成") |
| except: |
| self.print_log("备份pgsql出错") |
| self.print_log(public.get_error_info()) |
| self.change_backup_status("env_list", "pgsql", conf['name'], status_name="backup_status", status=2, msg="备份pgsql出错,程序出错") |
|
|
| def backup_nginx(self, conf): |
| try: |
| self.print_log("->>> 开始备份nginx") |
| flag = 1 |
| nginx_conf = None |
| nginx_version = None |
| nginx_file = None |
| nginx_cmd = None |
| nginx_systemd = None |
| self.change_backup_status("env_list", "nginx", conf['name'], status_name="backup_status", status=-1, msg="开始备份nginx") |
| if not conf['setup']: |
| self.print_log("nginx未安装") |
| self.change_backup_status("env_list", "nginx", status_name="backup_status", status=2, msg="nginx未安装") |
| flag = 2 |
| else: |
| self.print_log("开始备份nginx{}版本".format(conf["name"])) |
| nginx_version = conf["name"] |
| self.print_log("开始备份nginx{}配置文件".format(nginx_version)) |
| nginx_conf_path = "/www/server/nginx/conf/nginx.conf" |
| res = self.copy_file(nginx_conf_path) |
| if not res: |
| self.print_log("备份nginx{}配置文件失败".format(nginx_version)) |
| flag = 2 |
| else: |
| nginx_conf = res |
| self.print_log("开始备份nginx{}文件".format(nginx_version)) |
| nginx_file_path = "/www/server/nginx" |
| res = self.copy_file(nginx_file_path) |
| if not res: |
| self.print_log("备份nginx{}文件失败".format(nginx_version)) |
| flag = 2 |
| else: |
| nginx_file = res |
| self.print_log("开始备份nginx{}启动脚本".format(nginx_version)) |
| nginx_cmd_path = "/etc/init.d/nginx" |
| res = self.copy_file(nginx_cmd_path) |
| if not res: |
| self.print_log("备份nginx{}启动脚本失败".format(nginx_version)) |
| flag = 2 |
| else: |
| nginx_cmd = res |
| self.print_log("开始备份nginx{}systemd服务脚本".format(nginx_version)) |
| nginx_systemd_path = "/lib/systemd/system/nginx.service" |
| if os.path.exists(nginx_systemd_path): |
| res = self.copy_file(nginx_systemd_path) |
| if not res: |
| self.print_log("备份nginx{}systemd服务脚本失败".format(nginx_version)) |
| flag = 2 |
| else: |
| nginx_systemd = res |
| nginx_conf_md5 = self.get_md5(nginx_conf_path) |
| nginx_file_md5 = self.get_md5(nginx_file_path) |
| nginx_cmd_md5 = self.get_md5(nginx_cmd_path) |
| nginx_systemd_md5 = self.get_md5(nginx_systemd_path) |
| config = { |
| "nginx_conf": nginx_conf, |
| "nginx_file": nginx_file, |
| "nginx_cmd": nginx_cmd, |
| "nginx_systemd": nginx_systemd, |
| "version": nginx_version, |
| "nginx_conf_md5": nginx_conf_md5, |
| "nginx_file_md5": nginx_file_md5, |
| "nginx_cmd_md5": nginx_cmd_md5, |
| "nginx_systemd_md5": nginx_systemd_md5, |
| } |
| self.write_id_config("env_list", "nginx", config=config) |
| self.change_backup_status("env_list", "nginx", conf['name'], status_name="backup_status", status=flag, msg="备份nginx完成") |
| except: |
| self.print_log("备份nginx出错") |
| self.print_log(public.get_error_info()) |
| self.change_backup_status("env_list", "nginx", conf['name'], status_name="backup_status", status=2, msg="备份nginx出错,程序出错") |
|
|
| def backup_apache(self, conf): |
| try: |
| self.print_log("->>> 开始备份apache") |
| self.change_backup_status("env_list", "apache", conf['name'], status_name="backup_status", status=-1, msg="开始备份apache") |
| flag = 1 |
| apache_conf = None |
| apache_version = None |
| self.print_log("开始备份apache{}版本".format(conf["name"])) |
| version = apache_version |
| self.print_log("开始备份apache{}配置文件".format(version)) |
| apache_conf_path = "/www/server/apache/conf/" |
| res = self.copy_file(apache_conf_path) |
| if not res: |
| self.print_log("备份apache{}配置文件失败".format(version)) |
| flag = 2 |
| else: |
| apache_conf = res |
| apache_conf_md5 = self.get_md5(apache_conf_path) |
| config = { |
| "version": version, |
| "apache_conf": apache_conf, |
| "apache_conf_md5": apache_conf_md5, |
| } |
| self.write_id_config("env_list", "apache", config=config) |
| self.change_backup_status("env_list", "apache", conf['name'], status_name="backup_status", status=flag, msg="备份apache完成") |
| except: |
| self.print_log("备份apache出错") |
| self.print_log(public.get_error_info()) |
| self.change_backup_status("env_list", "apache", conf['name'], status_name="backup_status", status=2, msg="备份apache出错,程序出错") |
|
|
| def backup_ftp(self, conf): |
| try: |
| self.print_log("->>> 开始备份ftp") |
| self.change_backup_status("env_list", "ftp", conf['name'], status_name="backup_status", status=-1, msg="开始备份ftp") |
| flag = 1 |
| version = conf["name"] |
| ftp_conf = None |
| log_status = None |
| if not conf['setup']: |
| self.print_log("ftp未安装") |
| self.change_backup_status("env_list", "ftp", conf["name"], "backup_status", 2, msg="ftp未安装") |
| flag = 2 |
| else: |
| self.print_log("开始备份ftp{}配置文件".format(version)) |
| ftp_conf_path = "/www/server/pure-ftpd/etc/pure-ftpd.conf" |
| res = self.copy_file(ftp_conf_path) |
| if not res: |
| self.print_log("备份ftp{}配置文件失败".format(version)) |
| flag = 2 |
| else: |
| ftp_conf = res |
| self.print_log("开始备份ftp{}日志状态".format(version)) |
| rsyslog_path = "/etc/rsyslog.conf" |
| cofig = public.readFile(rsyslog_path) |
| if "ftp.*" in cofig: |
| log_status = 1 |
| else: |
| log_status = 0 |
| ftp_conf_md5 = self.get_md5(ftp_conf_path) |
| config = { |
| "version": version, |
| "ftp_conf": ftp_conf, |
| "log_status": log_status, |
| "ftp_conf_md5": ftp_conf_md5, |
| } |
| self.write_id_config("env_list", "ftp", config=config) |
| self.change_backup_status("env_list", "ftp", conf['name'], status_name="backup_status", status=flag, msg="备份ftp完成") |
| self.print_log("->>>备份ftp完成") |
| except: |
| self.print_log("备份ftp出错") |
| self.print_log(public.get_error_info()) |
| self.change_backup_status("env_list", "ftp", conf['name'], status_name="backup_status", status=2, msg="备份ftp出错,程序出错") |
|
|
| |
| |
| |
|
|
| def backup_data(self, conf): |
| data_conf = conf["data_list"] |
| connect = { |
| "php": self.backup_php_data, |
| "java": self.backup_java_data, |
| "node": self.backup_node_data, |
| "python": self.backup_python_data, |
| "other": self.backup_other_data, |
| "net": self.backup_net_data, |
| "proxy": self.backup_proxy_data, |
| "html": self.backup_html_data, |
| "mysql": self.backup_mysql_data, |
| "mongodb": self.backup_mongodb_data, |
| "redis": self.backup_redis_data, |
| "pgsql": self.backup_pgsql_data, |
| "ftp_list": self.backup_ftp_data, |
| "terminal_list": self.backup_terminal_data, |
| "crontab_list": self.backup_crontab_data, |
| "port_list": self.backup_port_data, |
| "ip_list": self.backup_ip_data, |
| "port_redirect": self.backup_port_redirect_data, |
| "area_list": self.backup_area_data, |
| "ssh_config": self.ssh_config_data, |
| "words": self.backup_words_data, |
| "sqlite": self.backup_sqlite_data, |
| } |
| for k, v in data_conf.items(): |
| if k in ['site_list', 'sql_list', 'config_list', "safety"]: |
| for type, dates in v.items(): |
| if type not in connect.keys(): |
| continue |
| for data in dates: |
| if data['status'] in [1, -1, 2]: |
| connect[type.lower()](data) |
| else: |
| if data['name'] and data["status"] != 3: |
| self.change_backup_status("data_list", k, type, "backup_status", 4, data["name"], msg="未备份".format(data["name"])) |
| elif k in ['ftp_list']: |
| for i in v: |
| if i['status'] in [1, -1, 2]: |
| connect[k](i) |
| else: |
| if i['name'] and i["status"] != 3: |
| self.change_backup_status("data_list", k, i["name"], "backup_status", 4, msg="未备份".format(i["name"])) |
| else: |
| for j in v: |
| if j['status'] in [1, -1, 2]: |
| connect[k](j) |
| else: |
| if j['name'] and j["status"] != 3: |
| self.change_backup_status("data_list", k, j["name"], "backup_status", 4, msg="未备份".format(j["name"])) |
|
|
| def backup_php_data(self, conf): |
| try: |
| self.print_log("->>>开始备份PHP站点:{}".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'php', "backup_status", -1, conf["name"], msg="开始备份") |
| |
| sid = conf["id"] |
| site_info = public.M('sites').where("id=?", (sid,)).find() |
| is_phpmod = False |
| if 'project_config' in site_info.keys(): |
| project_config = json.loads(site_info['project_config']) |
| if 'type' in project_config.keys() and project_config['type'].lower() == 'phpmod': |
| is_phpmod = True |
| site_file = None |
| domains = None |
| database_info = None |
| redirect_list = [] |
| redirect_nginx_data = None |
| redirect_apache_data = None |
| proxy_nginx_data = None |
| proxy_apache_data = None |
| proxy_list = [] |
| nginx_config = None |
| apache_config = None |
| dir_auth_json = None |
| dir_auth_file = None |
| ssl_info = None |
| if not site_info: |
| self.print_log("{} 获取站点信息失败".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'php', "backup_status", 2, conf["name"], msg="获取站点信息失败") |
| else: |
| |
| domains = public.M('domain').where("pid=?", (sid,)).select() |
| if not domains or isinstance(domains, str): |
| self.print_log("{} 获取站点域名失败".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'php', "backup_status", 2, conf["name"], msg="获取站点域名失败") |
|
|
| |
| site_file_path = site_info["path"] |
| if os.path.exists(site_file_path): |
| site_file = self.copy_file(site_file_path) |
|
|
| |
| database_info = public.M("databases").where("pid = ?", (sid,)).find() |
| if not database_info: |
| database_info = None |
| self.print_log("未查找到相关的数据库信息,跳过备份数据库") |
| elif isinstance(database_info, str): |
| database_info = None |
| self.print_log("查找数据库信息失败,跳过备份数据库") |
| if database_info is not None: |
| self.backup_mysql_data(database_info) |
| |
| ftp_info = public.M("ftps").where("pid = ?", (sid,)).find() |
| if not ftp_info: |
| ftp_info = None |
| self.print_log("未查找到相关的ftp信息,跳过备份ftp") |
| elif isinstance(ftp_info, str): |
| ftp_info = None |
| self.print_log("查找ftp信息失败,跳过备份ftp") |
| if ftp_info is not None: |
| self.backup_ftp_data(ftp_info) |
| __redirectfile = "/www/server/panel/data/redirect.conf" |
| try: |
| redirectconf = json.loads(public.readFile(__redirectfile)) |
| except: |
| redirectconf = {} |
| for i in redirectconf: |
| if i["sitename"] == conf["name"]: |
| redirect_list.append(i) |
| redirect_nginx_data_path = '/www/server/panel/vhost/nginx/redirect/{}'.format(conf["name"]) |
| redirect_nginx_data = self.copy_file(redirect_nginx_data_path) |
| redirect_apache_data_path = '/www/server/panel/vhost/apache/redirect/{}'.format(conf["name"]) |
| redirect_apache_data = self.copy_file(redirect_apache_data_path) |
| if not is_phpmod: |
| __proxyfile = '{}/data/proxyfile.json'.format(public.get_panel_path()) |
|
|
| else: |
| __proxyfile = "{}/data/mod_proxy_file.conf".format(public.get_panel_path()) |
| try: |
| proxyUrl = json.loads(public.readFile(__proxyfile)) |
| except: |
| proxyUrl = {} |
| for i in proxyUrl: |
| if i["sitename"] == conf["name"]: |
| proxy_list.append(i) |
| proxy_nginx_data_path = '/www/server/panel/vhost/nginx/proxy/{}'.format(conf["name"]) |
| proxy_nginx_data = self.copy_file(proxy_nginx_data_path) |
| proxy_apache_data_path = '/www/server/panel/vhost/apache/proxy/{}'.format(conf["name"]) |
| proxy_apache_data = self.copy_file(proxy_apache_data_path) |
|
|
| import panelSite |
| |
| site_run_path = panelSite.panelSite().GetDirUserINI(public.to_dict_obj({'path': site_info['path'], 'id': site_info['id']})) |
| import config |
| |
| ssl_path = "/www/server/panel/vhost/cert/{}".format(site_info["name"]) |
| if os.path.exists(ssl_path): |
| ssl_info = self.copy_file(ssl_path) |
|
|
| |
| nginx_config_path = "/www/server/panel/vhost/nginx/{}.conf".format(site_info["name"]) |
| apache_config_path = "/www/server/panel/vhost/apache/{}.conf".format(site_info["name"]) |
| if os.path.exists(nginx_config_path): |
| nginx_config = self.copy_file(nginx_config_path) |
| if os.path.exists(apache_config_path): |
| apache_config = self.copy_file(apache_config_path) |
|
|
| |
| dir_auth_json_path = "/www/server/panel/data/site_dir_auth.json" |
| if os.path.exists(dir_auth_json_path): |
| dir_auth_json = self.copy_file(dir_auth_json_path) |
| dir_auth_file_path = "/www/server/panel/vhost/nginx/dir_auth/{}".format(site_info["name"]) |
| if os.path.exists(dir_auth_file_path): |
| dir_auth_file = self.copy_file(dir_auth_file_path) |
|
|
| banding = public.M('binding').where('pid=?', (site_info['id'],)).field('id,pid,domain,path,port,addtime').select() |
|
|
| site_file_md5 = self.get_md5(site_file_path) |
| nginx_config_md5 = self.get_md5(nginx_config_path) |
| apache_config_md5 = self.get_md5(apache_config_path) |
| dir_auth_json_md5 = self.get_md5(dir_auth_json_path) |
| dir_auth_file_md5 = self.get_md5(dir_auth_file_path) |
|
|
| |
| pseudo_static_data_path = "/www/server/panel/vhost/rewrite/{}.conf".format(site_info["name"]) |
| pseudo_static_data_md5 = self.get_md5(pseudo_static_data_path) |
| pseudo_static_data = self.copy_file(pseudo_static_data_path) |
|
|
| php_version = panelSite.panelSite().GetSitePHPVersion(public.to_dict_obj({'siteName': site_info['name']}))['phpversion'] |
| site_info["php_version"] = php_version |
| config = { |
| "site_file": site_file, |
| "domains": domains, |
| "database_info": database_info, |
| "redirect_list": redirect_list, |
| "proxy_list": proxy_list, |
| "site_run_path": site_run_path, |
| "ssl_info": ssl_info, |
| "nginx_config": nginx_config, |
| "apache_config": apache_config, |
| "dir_auth_file": dir_auth_file, |
| "dir_auth_json": dir_auth_json, |
| "banding": banding, |
| "site_file_md5": site_file_md5, |
| "nginx_config_md5": nginx_config_md5, |
| "apache_config_md5": apache_config_md5, |
| "dir_auth_json_md5": dir_auth_json_md5, |
| "dir_auth_file_md5": dir_auth_file_md5, |
| "site_info": site_info, |
| "ftp_info": ftp_info, |
| "pseudo_static_data": pseudo_static_data, |
| "pseudo_static_data_md5": pseudo_static_data_md5, |
| "redirect_nginx_data": redirect_nginx_data, |
| "redirect_apache_data": redirect_apache_data, |
| "proxy_nginx_data": proxy_nginx_data, |
| "proxy_apache_data": proxy_apache_data, |
| } |
| self.print_log(config) |
| self.write_id_config("data_list", "site_list", "php", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "site_list", 'php', "backup_status", 1, conf["name"], msg="备份PHP站点:{}完成".format(conf["name"])) |
| self.print_log("->>>备份PHP站点:{}完成".format(conf["name"])) |
| except: |
| self.change_backup_status("data_list", "site_list", 'php', "backup_status", 2, conf["name"], msg="备份PHP站点:{}出错,程序出错".format(conf["name"])) |
| self.print_log("备份PHP站点:{}出错".format(conf["name"])) |
| self.print_log(public.get_error_info()) |
|
|
| def backup_java_data(self, conf): |
| self.print_log("->>>备份Java站点:{},跳过".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'java', "backup_status", 2, conf["name"]) |
| return |
| self.print_log("->>>开始备份Java站点:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>备份Java站点:{}完成".format(conf["name"])) |
|
|
| def backup_node_data(self, conf): |
| self.print_log("->>>备份Node站点:{}跳过".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'node', "backup_status", 2, conf["name"], msg="备份Node站点:{}跳过".format(conf["name"])) |
| return |
| self.print_log("->>>开始备份Node站点:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>备份Node站点:{}完成".format(conf["name"])) |
|
|
| def backup_python_data(self, conf): |
| self.print_log("->>>备份Python站点:{}跳过".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'python', "backup_status", 2, conf["name"], msg="备份Python站点:{}跳过".format(conf["name"])) |
| return |
| self.print_log("->>>开始备份Python站点:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>备份Python站点:{}完成".format(conf["name"])) |
|
|
| def backup_other_data(self, conf): |
| self.print_log("->>>备份其他站点:{}跳过".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'other', "backup_status", 2, conf["name"], msg="备份其他站点:{}跳过".format(conf["name"])) |
| return |
| self.print_log("->>>开始备份其他站点:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>备份其他站点:{}完成".format(conf["name"])) |
|
|
| def backup_net_data(self, conf): |
| self.print_log("->>>备份.NET站点:{}跳过".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'net', "backup_status", 2, conf["name"], msg="备份.NET站点:{}跳过".format(conf["name"])) |
| return |
| self.print_log("->>>开始备份.NET站点:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>备份.NET站点:{}完成".format(conf["name"])) |
|
|
| def backup_proxy_data(self, conf): |
| self.print_log("->>>开始备份代理站点:{}".format(conf["name"])) |
| nginx_config = None |
| apache_config = None |
| site_info = None |
| site_info = public.M('sites').where("name=?", (conf["name"],)).select() |
| self.print_log("数据库信息备份成功") |
| proxy_config_path = "/www/server/proxy_project/sites/{}".format(conf["name"]) |
| if not os.path.exists(proxy_config_path): |
| self.print_log("代理站点:{},配置文件不存在,备份失败".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'proxy', "backup_status", 2, conf["name"], msg="代理站点:{},配置文件不存在,备份失败".format(conf["name"])) |
| return |
| proxy_config = self.copy_file(proxy_config_path) |
| self.print_log("代理站点:{}配置文件备份成功".format(conf["name"])) |
| nginx_config_path = "/www/server/panel/vhost/nginx/{}.conf".format(conf["name"]) |
| if os.path.exists(nginx_config_path): |
| nginx_config = self.copy_file(nginx_config_path) |
| apache_config_path = "/www/server/panel/vhost/apache/{}.conf".format(conf["name"]) |
| if os.path.exists(apache_config_path): |
| apache_config = self.copy_file(apache_config_path) |
| self.print_log("代理站点:{}web配置文件备份成功".format(conf["name"])) |
|
|
| proxy_config_md5 = self.get_md5(proxy_config_path) |
| nginx_config_md5 = self.get_md5(nginx_config_path) |
| apache_config_md5 = self.get_md5(apache_config_path) |
|
|
| config = { |
| "proxy_config": proxy_config, |
| "nginx_config": nginx_config, |
| "apache_config": apache_config, |
| "site_info": site_info, |
| "proxy_config_md5": proxy_config_md5, |
| "nginx_config_md5": nginx_config_md5, |
| "apache_config_md5": apache_config_md5, |
| } |
| self.write_id_config("data_list", "site_list", "proxy", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "site_list", 'proxy', "backup_status", 1, conf["name"], msg="备份代理站点:{}完成".format(conf["name"])) |
| self.print_log("->>>备份代理站点:{}完成".format(conf["name"])) |
|
|
| def backup_html_data(self, conf): |
| self.print_log("->>>备份静态站点:{}跳过".format(conf["name"])) |
| self.change_backup_status("data_list", "site_list", 'html', "backup_status", 2, conf["name"], msg="备份静态站点:{}跳过".format(conf["name"])) |
| return |
| self.print_log("->>>开始备份静态站点:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>备份静态站点:{}完成".format(conf["name"])) |
|
|
| |
| def check_mysql_files(self, sql_path, sql_name): |
| if not os.path.exists(sql_path): |
| self.print_log("备份mysql数据库:{}失败,备份文件不存在!".format(sql_name)) |
| return False |
| if os.path.isdir(sql_path): |
| self.print_log("备份mysql数据库:{}失败,备份文件为目录!".format(sql_name)) |
| return False |
| |
| sql_size = os.path.getsize(sql_path) |
| if sql_size > 10 * 1024 * 1024: |
| self.print_log("备份mysql数据库:{},备份文件大于10M,跳过数据校验!".format(sql_name)) |
| return True |
| |
| data = public.GetNumLines(sql_path, 3) |
| if data.find("Dump completed on") == -1: |
| self.print_log("备份mysql数据库:{}失败,备份非正常结束!".format(sql_name)) |
| return False |
| |
| |
| table_list = database.database().GetInfo(public.to_dict_obj({'db_name': sql_name})) |
| table_list = [i['table_name'] for i in table_list["tables"]] |
| if not table_list: |
| self.print_log("备份mysql数据库:{}数据校验成功,数据库无表".format(sql_name)) |
| return True |
|
|
| self.print_log(table_list) |
| res = public.ExecShell("grep -o -F -e {} {}".format(" -e ".join(table_list), sql_path))[0] |
| |
| res = list(set(res.split("\n"))) |
| res = [i.strip() for i in res if i.strip()] |
| if len(res) != len(table_list): |
| self.print_log("备份mysql数据库:{}失败,备份文件不完整!".format(sql_name)) |
| return False |
| self.print_log("备份mysql数据库:{}数据校验成功".format(sql_name)) |
| return True |
|
|
| def backup_mysql_data(self, conf): |
| try: |
| self.print_log("->>>开始备份mysql数据库:{}".format(conf["name"])) |
| self.print_log(conf) |
| sql_data_md5 = None |
| self.change_backup_status("data_list", "sql_list", 'mysql', "backup_status", -1, conf["name"], msg="开始备份mysql数据库:{}".format(conf["name"])) |
| mysql_info = public.M("databases").where("name=?", (conf['name'],)).find() |
| if not mysql_info or isinstance(mysql_info, str): |
| self.print_log("获取mysql数据库信息失败") |
| self.change_backup_status("data_list", "sql_list", 'mysql', "backup_status", 2, conf["name"], msg="获取mysql数据库信息失败") |
| return |
| |
| if mysql_info["db_type"] == 2: |
| config = { |
| "mysql_info": mysql_info, |
| "cloud_server": public.M('database_servers').where('id=?', (mysql_info['sid'])).select() |
| } |
| if not config["cloud_server"]: |
| self.print_log("获取远程数据库信息失败") |
| self.change_backup_status("data_list", "sql_list", 'mysql', "backup_status", 2, conf["name"], msg="获取远程数据库信息失败") |
| return |
| else: |
| config["cloud_server"] = config["cloud_server"][0] |
| self.write_id_config("data_list", "sql_list", "mysql", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'mysql', "backup_status", 1, conf["name"]) |
| self.print_log("->>>备份mysql数据库:{}完成,远程数据库".format(conf["name"])) |
| return |
| self.print_log("32") |
| sql_path = '/tmp/{}.sql'.format(conf["name"]) |
| md5_name = self.generate_md5(sql_path) |
| save_path = os.path.join(self.backup_path, "backup", md5_name) |
| sql_data = save_path |
| if not os.path.exists(save_path): |
| if not os.path.exists(self.backup_path): |
| self.print_log("333333333332") |
| os.makedirs(self.backup_path) |
| _MYSQLDUMP_BIN = public.get_mysqldump_bin() |
| db_password = public.M("config").where("id=?", (1,)).getField("mysql_root") |
| self.print_log("33333333333333333333332") |
| try: |
| db_port = int(panelMysql.panelMysql().query("show global variables like 'port'")[0][1]) |
| except: |
| db_port = 3306 |
| mysql_obj = db_mysql.panelMysql() |
| flag = mysql_obj.set_host('localhost', db_port, None, 'root', db_password) |
| if flag is False: |
| self.print_log("连接mysql数据库失败") |
| self.change_backup_status("data_list", "sql_list", 'mysql', "backup_status", 2, conf["name"], msg="连接mysql数据库失败") |
| return |
| |
| resp = public.ExecShell("{} --help | grep set-gtid-purged >> /tmp/backup_sql.log".format(_MYSQLDUMP_BIN))[0] |
| set_gtid_purged = '' |
| if resp.find("--set-gtid-purged") != -1: |
| set_gtid_purged = "--set-gtid-purged=OFF" |
| shell = "'{mysqldump_bin}' {set_gtid_purged} --opt --skip-lock-tables --single-transaction --routines --events --skip-triggers --default-character-set='{db_charset}' --force " \ |
| "--host='{db_host}' --port={db_port} --user='{db_user}' --password='{db_password}' '{db_name}' > {sql_path}".format( |
| mysqldump_bin=_MYSQLDUMP_BIN, |
| set_gtid_purged=set_gtid_purged, |
| db_charset='utf8mb4', |
| db_host='localhost', |
| db_port=db_port, |
| db_user='root', |
| db_password=db_password, |
| db_name=conf["name"], |
| sql_path=sql_path |
| ) |
| public.ExecShell(shell) |
| if not self.check_mysql_files(sql_path, conf["name"]): |
| self.print_log("3333333333333333333333333333333") |
| self.change_backup_status("data_list", "sql_list", 'mysql', "backup_status", 2, conf["name"], msg="备份mysql数据库:{}失败".format(conf["name"])) |
| self.print_log("333333333333333333333333333333333333333333333333333") |
| return |
| time.sleep(0.1) |
| if os.path.exists(sql_path): |
| |
| sql_data_md5 = self.get_md5(sql_path) |
| sql_data = self.copy_file(sql_path) |
| self.print_log("备份mysql数据库:{}数据打包成功!".format(conf["name"])) |
| public.ExecShell('rm -rf {}'.format(sql_path)) |
|
|
| |
| sql_power = database.database().GetDatabaseAccess(public.to_dict_obj({'name': conf["name"]}))['msg'] |
| sql_info = database.database().GetInfo(public.to_dict_obj({'db_name': conf["name"]})) |
| mysql_version = public.readFile('/www/server/mysql/version.pl') |
| config = { |
| "sql_data": sql_data, |
| "mysql_info": mysql_info, |
| "sql_power": sql_power, |
| "sql_info": sql_info, |
| "mysql_version": mysql_version, |
| "sql_data_md5": sql_data_md5, |
| } |
| self.print_log(config) |
| self.print_log("3333333333333333333") |
| self.write_id_config("data_list", "sql_list", "mysql", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'mysql', "backup_status", 1, conf["name"], msg="备份mysql数据库:{}完成".format(conf["name"])) |
| self.print_log("->>>备份mysql数据库:{}完成".format(conf["name"])) |
| except: |
| print(public.get_error_info()) |
|
|
| def backup_mongodb_data(self, conf): |
| self.print_log("->>>开始备份mongo数据库:{}".format(conf["name"])) |
| mongo_info = public.M("databases").where("name=? AND LOWER(type)=LOWER('mongodb')", (conf['name'],)).find() |
| if not mongo_info or isinstance(mongo_info, str): |
| self.print_log("获取mongo数据库信息失败") |
| self.change_backup_status("data_list", "sql_list", 'mongodb', "backup_status", 2, conf["name"], msg="获取mongo数据库信息失败") |
| return |
| |
| if mongo_info["db_type"] == 2: |
| config = { |
| "mongo_info": mongo_info, |
| "cloud_server": public.M('database_servers').where('db_type=?', ('mongodb')).select() |
| } |
| self.write_id_config("data_list", "sql_list", "mongodb", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'mongodb', "backup_status", 1, conf["name"], msg="备份mongo数据库:{}完成".format(conf["name"])) |
| return |
|
|
| |
| mongo_path = '/tmp/{}'.format(conf["name"]) |
| md5_name = self.generate_md5(mongo_path) |
| save_path = os.path.join(self.backup_path, "backup", md5_name) |
| mongo_data = save_path |
| mongo_data_md5 = None |
| if not os.path.exists(save_path): |
| _MONGODBDUMP_BIN = os.path.join(public.get_setup_path(), "mongodb/bin/mongodump") |
| _MONGOEXPORT_BIN = os.path.join(public.get_setup_path(), "mongodb/bin/mongoexport") |
| db_password = mongo_info["password"] |
| from databaseModel.mongodbModel import panelMongoDB |
| if mongo_info["db_type"] == 0: |
| if panelMongoDB().get_config_options("security", "authorization", "disabled") == "enabled": |
| if not db_password: |
| return public.returnMsg(False, "数据库密码为空!请先设置数据库密码!") |
| else: |
| db_password = None |
| db_port = panelMongoDB.get_config_options("net", "port", 27017) |
| db_host = "127.0.0.1" |
| db_user = mongo_info["username"] |
| mongodump_shell = "'{mongodump_bin}' --host='{db_host}' --port={db_port} --db='{db_name}' --out='{out}'".format( |
| mongodump_bin=_MONGODBDUMP_BIN, |
| db_host=db_host, |
| db_port=int(db_port), |
| db_name=conf["name"], |
| out=mongo_path, |
| ) |
| if db_password: |
| mongodump_shell += " --username='{db_user}' --password={db_password}".format(db_user=db_user, db_password=public.shell_quote(str(db_password))) |
|
|
| public.ExecShell('{}'.format(mongodump_shell)) |
| time.sleep(0.1) |
| if os.path.exists(mongo_path): |
| self.print_log("备份mongo数据库:{}完成".format(conf["name"])) |
| |
| mongo_data = self.copy_file(mongo_path) |
| mongo_data_md5 = self.get_md5(mongo_path) |
| public.ExecShell('rm -rf {}'.format(mongo_path)) |
| from databaseModel.mongodbModel import main |
| sql_power = main().GetDatabaseAccess(public.to_dict_obj({'user_name': mongo_info["username"]}))['data'] |
| config = { |
| "mongo_data": mongo_data, |
| "mongo_info": mongo_info, |
| "sql_power": sql_power, |
| "mongo_data_md5": mongo_data_md5 |
| } |
| self.print_log(config) |
| self.write_id_config("data_list", "sql_list", "mongodb", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'mongodb', "backup_status", 1, conf["name"], msg="备份mongo数据库:{}完成".format(conf["name"])) |
| self.print_log("->>>备份mongo数据库:{}完成".format(conf["name"])) |
|
|
| def backup_redis_data(self, conf): |
| self.print_log("->>>开始备份redis数据库:{}".format(conf["name"])) |
| from databaseModel.redisModel import panelRedisDB |
| redis_db = panelRedisDB().set_host(decode_responses=False) |
| status, redis_obj = redis_db.connect(0) |
| if status is False: |
| self.print_log("连接redis数据库失败") |
| self.change_backup_status("data_list", "sql_list", 'redis', "backup_status", 2, conf["name"], msg="连接redis数据库失败") |
| return |
| redis_obj.bgsave() |
|
|
| |
| while True: |
| |
| progress_info = redis_obj.info("persistence") |
| bgsave_in_progress = int(progress_info.get("rdb_bgsave_in_progress", 0)) |
| if bgsave_in_progress == 0: |
| break |
| time.sleep(1) |
| dump_path = os.path.join(redis_obj.config_get("dir")["dir"], redis_obj.config_get("dbfilename")["dbfilename"]) |
| if not os.path.exists(dump_path): |
| self.print_log("备份redis数据库:{}失败".format(conf["name"])) |
| self.change_backup_status("data_list", "sql_list", 'redis', "backup_status", 2, conf["name"], msg="备份redis数据库:{}失败".format(conf["name"])) |
| return |
| redis_data = self.copy_file(dump_path) |
| redis_data_md5 = self.get_md5(dump_path) |
| public.ExecShell('rm -rf {}'.format(dump_path)) |
| config = { |
| "redis_data": redis_data, |
| "redis_info": conf, |
| "redis_data_md5": redis_data_md5 |
| } |
| self.print_log(config) |
| self.write_id_config("data_list", "sql_list", "redis", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'redis', "backup_status", 1, conf["name"], msg="备份redis数据库:{}完成".format(conf["name"])) |
| self.print_log("->>>备份redis数据库:{}完成".format(conf["name"])) |
|
|
| def backup_pgsql_data(self, conf): |
| self.print_log("->>>开始备份pgsql数据库:{}".format(conf["name"])) |
| pgsql_info = public.M("databases").where("name=? AND LOWER(type)=LOWER('pgsql')", (conf['name'],)).find() |
| self.print_log(pgsql_info) |
| pgsql_data = None |
| if not pgsql_info or isinstance(pgsql_info, str): |
| self.print_log("获取pgsql数据库信息失败") |
| self.change_backup_status("data_list", "sql_list", 'pgsql', "backup_status", 2, conf["name"], msg="获取pgsql数据库信息失败") |
| return |
| |
| if pgsql_info["db_type"] == 2: |
| config = { |
| "pgsql_info": pgsql_info, |
| "cloud_server": public.M('database_servers').where('db_type=?', ('pgsql')).select() |
| } |
| self.write_id_config("data_list", "sql_list", "pgsql", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'pgsql', "backup_status", 1, conf["name"], msg="备份pgsql数据库:{}完成".format(conf["name"])) |
| self.print_log("->>>备份pgsql数据库:{}完成".format(conf["name"])) |
| return |
|
|
| |
| db_name = pgsql_info["name"] |
| pgsql_data_md5 = None |
| db_user = "postgres" |
| db_host = "127.0.0.1" |
| from databaseModel.pgsqlModel import panelPgsql |
| db_port = panelPgsql().get_config_options("port", int, 5432) |
| t_path = os.path.join(public.get_panel_path(), "data/postgresAS.json") |
| if not os.path.isfile(t_path): |
| self.change_backup_status("data_list", "sql_list", 'pgsql', "backup_status", 2, conf["name"], msg="获取数据库密码失败") |
| self.print_log("获取数据库密码失败") |
| db_password = "" |
| if os.path.exists(t_path): |
| try: |
| db_password = json.loads(public.readFile(t_path)).get("password", "") |
| except: |
| db_password = "" |
| if not db_password: |
| self.change_backup_status("data_list", "sql_list", 'pgsql', "backup_status", 2, conf["name"], msg="获取数据库密码失败") |
| self.print_log("获取数据库密码失败") |
| return |
|
|
| pgsql_obj = panelPgsql().set_host(host=db_host, port=db_port, database=None, user=db_user, password=db_password) |
| status, err_msg = pgsql_obj.connect() |
| if status is False: |
| self.change_backup_status("data_list", "sql_list", 'pgsql', "backup_status", 2, conf["name"], msg="连接数据库失败[{}:{}]".format(db_host, db_port)) |
| self.print_log("连接数据库失败[{}:{}]".format(db_host, db_port)) |
| return |
| _PGDUMP_BIN = os.path.join(public.get_setup_path(), "pgsql/bin/pg_dump") |
| backup_path = '/tmp/{}.sql'.format(db_name) |
| md5_name = self.generate_md5(backup_path) |
| pgsql_data = os.path.join(self.backup_path, "backup", md5_name) |
| if not os.path.exists(backup_path): |
| shell = "'{pgdump_bin}' --host='{db_host}' --port={db_port} --username='{db_user}' --dbname='{db_name}' --clean > {backup_path}".format( |
| pgdump_bin=_PGDUMP_BIN, |
| db_host=db_host, |
| db_port=int(db_port), |
| db_user=db_user, |
| db_name=db_name, |
| backup_path=backup_path |
| ) |
| public.ExecShell(shell) |
| time.sleep(0.1) |
| if os.path.exists(backup_path): |
| self.print_log("备份pgsql数据库:{}完成".format(conf["name"])) |
| |
| pgsql_data = self.copy_file(backup_path) |
| pgsql_data_md5 = self.get_md5(backup_path) |
| public.ExecShell('rm -rf {}'.format(backup_path)) |
| config = { |
| "pgsql_data": pgsql_data, |
| "pgsql_info": pgsql_info, |
| "pgsql_data_md5": pgsql_data_md5 |
| } |
| self.print_log(config) |
| self.write_id_config("data_list", "sql_list", "pgsql", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'pgsql', "backup_status", 1, conf["name"], msg="备份pgsql数据库:{}完成".format(conf["name"])) |
| self.print_log("->>>备份pgsql数据库:{}完成".format(conf["name"])) |
|
|
| def backup_sqlServer_data(self, conf): |
| self.print_log("->>>开始备份sqlServer数据库:{}".format(conf["name"])) |
| sql_info = public.M("databases").where("name=? AND LOWER(type)=LOWER('sqlserver')", (conf['name'],)).find() |
| if not sql_info or isinstance(sql_info, str): |
| self.print_log("获取sqlServer数据库信息失败") |
| self.change_backup_status("data_list", "sql_list", 'sqlserver', "backup_status", 2, conf["name"], msg="获取sqlServer数据库信息失败") |
| return |
| |
| config = { |
| "sql_info": sql_info, |
| "cloud_server": public.M('database_servers').where('db_type=?', ('sqlserver')).select() |
| } |
| self.write_id_config("data_list", "sql_list", "sqlserver", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", 'sqlserver', "backup_status", 1, conf["name"], msg="备份sqlServer数据库:{}完成".format(conf["name"])) |
| self.print_log("->>>备份sqlServer数据库:{}完成".format(conf["name"])) |
| return |
|
|
| def backup_ftp_data(self, conf): |
| self.print_log("->>>开始备份ftp:{}".format(conf["name"])) |
| self.print_log(conf) |
| ftp_info = public.M("ftps").where("id=?", (conf["id"],)).find() |
| if not ftp_info or isinstance(ftp_info, str): |
| self.print_log("获取ftp信息失败") |
| self.change_backup_status("data_list", "ftp_list", "ftp", "backup_status", 2, conf["name"], msg="获取ftp信息失败") |
| return |
| ftp_data = None |
| if os.path.exists(ftp_info["path"]): |
| ftp_data = self.copy_file(ftp_info["path"]) |
| ftp_data_md5 = self.get_md5(ftp_info["path"]) |
| config = { |
| "ftp_data": ftp_data, |
| "ftp_info": ftp_info, |
| "ftp_data_md5": ftp_data_md5 |
| } |
| self.print_log(config) |
| self.write_id_config("data_list", "ftp_list", conf["name"], config=config) |
| self.change_backup_status("data_list", "ftp_list", conf['name'], "backup_status", 1, msg="备份ftp:{}完成".format(conf["name"])) |
| self.print_log("->>>备份ftp:{}完成".format(conf["name"])) |
|
|
| def backup_terminal_data(self, conf): |
| self.print_log("->>>开始备份服务器列表,常用命令") |
| self.print_log(conf) |
| terminal_data = None |
| terminal_data_path = '/www/server/panel/config/ssh_info' |
| if os.path.exists(terminal_data_path): |
| terminal_data = self.copy_file(terminal_data_path) |
| terminal_data_md5 = self.get_md5(terminal_data_path) |
| config = { |
| "terminal_data": terminal_data, |
| "terminal_data_md5": terminal_data_md5, |
| } |
| self.write_id_config("data_list", "terminal_list", "服务器列表", config=config) |
| self.write_id_config("data_list", "terminal_list", "常用命令", config=config) |
| self.change_backup_status("data_list", "terminal_list", "服务器列表", "backup_status", 1, msg="备份服务器列表完成") |
| self.change_backup_status("data_list", "terminal_list", "常用命令", "backup_status", 1, msg="备份常用命令完成") |
| self.print_log("->>>备份服务器列表,常用命令完成") |
|
|
| def backup_crontab_data(self, conf): |
| self.print_log("->>>开始备份计划任务:{}".format(conf["name"])) |
| crontab_list = public.M("crontab").select() |
| self.write_id_config("data_list", "crontab_list", "crontab", config=crontab_list) |
| self.change_backup_status("data_list", "crontab_list", "计划任务列表", "backup_status", 1, msg="备份计划任务完成") |
| self.print_log("->>>备份计划任务:{}完成".format(conf["name"])) |
|
|
| def backup_port_data(self, conf): |
| self.print_log("->>>开始备份端口:{}".format(conf["name"])) |
| self.print_log(conf) |
| from firewallModel.comModel import main as com |
| port_data = None |
| port_data_md5 = None |
| try: |
| port_data_path = com().export_rules(public.to_dict_obj({"data": {'rule_name': 'port_rule'}}))['msg'] |
| port_data = self.copy_file(port_data_path) |
| port_data_md5 = self.get_md5(port_data_path) |
| except: |
| self.change_backup_status("data_list", "safety", "port_list", "backup_status", 2, conf["name"], msg="备份端口:{}出错,程序出错".format(conf["name"])) |
| self.print_log("备份端口:{}出错".format(conf["name"])) |
| return |
| config = { |
| "port_data": port_data, |
| "port_data_md5": port_data_md5, |
| "port_data_path": port_data_path |
| } |
| self.print_log(config) |
| self.write_id_config("data_list", "safety", "port_list", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "safety", "port_list", "backup_status", 1, conf["name"], msg="备份端口:{}完成".format(conf["name"])) |
| self.print_log("->>>备份端口:{}完成".format(conf["name"])) |
|
|
| def backup_ip_data(self, conf): |
| self.print_log("->>>开始备份IP:{}".format(conf["name"])) |
| from firewallModel.comModel import main as com |
| ip_data = None |
| ip_data_md5 = None |
| try: |
| ip_list_path = com().export_rules(public.to_dict_obj({"rule": 'ip', 'chain': 'ALL'}))['msg'] |
| ip_data = self.copy_file(ip_list_path) |
| ip_data_md5 = self.get_md5(ip_list_path) |
| except: |
| self.change_backup_status("data_list", "safety", "ip_list", "backup_status", 2, conf["name"], msg="备份IP:{}出错,程序出错".format(conf["name"])) |
| print(public.get_error_info()) |
| self.print_log("备份IP:{}出错".format(conf["name"])) |
| return |
| config = { |
| "ip_data": ip_data, |
| "ip_data_md5": ip_data_md5, |
| "ip_list_path": ip_list_path |
| } |
| self.write_id_config("data_list", "safety", "ip_list", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "safety", "ip_list", "backup_status", 1, conf["name"], msg="备份IP:{}完成".format(conf["name"])) |
| self.print_log(config) |
| self.print_log("->>>备份IP:{}完成".format(conf["name"])) |
|
|
| def backup_port_redirect_data(self, conf): |
| self.print_log("->>>开始备份端口转发:{}".format(conf["name"])) |
| from firewallModel.comModel import main as com |
| forward = None |
| forward_md5 = None |
| try: |
| forward_path = com().export_rules(public.to_dict_obj({"rule": 'forward'}))['msg'] |
| forward = self.copy_file(forward_path) |
| forward_md5 = self.get_md5(forward_path) |
| except: |
| self.change_backup_status("data_list", "safety", "ip_list", "port_redirect", 2, conf["name"], msg="备份IP:{}出错,程序出错".format(conf["name"])) |
| print(public.get_error_info()) |
| self.print_log("备份IP:{}出错".format(conf["name"])) |
| return |
| config = { |
| "forward": forward, |
| "forward_md5": forward_md5, |
| "forward_path": forward_path |
| } |
| self.write_id_config("data_list", "safety", "port_redirect", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "safety", "port_redirect", "backup_status", 1, conf["name"], msg="备份端口转发:{}完成".format(conf["name"])) |
| self.print_log(config) |
| self.print_log("->>>备份端口转发:{}完成".format(conf["name"])) |
|
|
| def backup_area_data(self, conf): |
| self.print_log("->>>开始备份区域:{}".format(conf["name"])) |
| area_data = None |
| area_data_md5 = None |
| try: |
| area_data_path = safe_firewall_main().export_rules(public.to_dict_obj({'rule_name': 'country_rule'}))['msg'] |
| area_data = self.copy_file(area_data_path) |
| area_data_md5 = self.get_md5(area_data_path) |
| except: |
| self.change_backup_status("data_list", "safety", "area_list", "backup_status", 2, conf["name"], msg="备份区域:{}出错,程序出错".format(conf["name"])) |
| self.print_log("备份区域:{}出错".format(conf["name"])) |
| return |
| config = { |
| "area_data": area_data, |
| "area_data_md5": area_data_md5, |
| "area_data_path": area_data_path |
| } |
| self.write_id_config("data_list", "safety", "area_list", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "safety", "area_list", "backup_status", 1, conf["name"], msg="备份区域:{}完成".format(conf["name"])) |
| self.print_log("->>>备份区域:{}完成".format(conf["name"])) |
|
|
| def ssh_config_data(self, conf): |
| self.print_log("->>>开始备份SSH配置:{}".format(conf["name"])) |
| ssh_data = None |
| ssh_data_md5 = None |
| ssh_config_path = '/etc/ssh/sshd_config' |
| if os.path.exists(ssh_config_path): |
| ssh_data = self.copy_file(ssh_config_path) |
| ssh_data_md5 = self.get_md5(ssh_config_path) |
| else: |
| self.print_log("未找到SSH配置文件") |
| self.change_backup_status("data_list", "safety", "ssh_config", "backup_status", 2, conf["name"], msg="未找到SSH配置文件") |
| return |
| config = { |
| "ssh_data": ssh_data, |
| "ssh_data_md5": ssh_data_md5 |
| } |
| self.write_id_config("data_list", "safety", "ssh_config", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "safety", "ssh_config", "backup_status", 1, conf["name"], msg="备份SSH配置:{}完成".format(conf["name"])) |
| self.print_log(config) |
| self.print_log("->>>备份SSH配置:{}完成".format(conf["name"])) |
|
|
| def backup_words_data(self, conf): |
| self.print_log("->>>开始备份关键词:{}".format(conf["name"])) |
| words_path = "/www/server/panel/config/thesaurus.json" |
| wrods_data = None |
| wrod_data_md5 = None |
| if os.path.exists(words_path): |
| wrods_data = self.copy_file(words_path) |
| wrod_data_md5 = self.get_md5(words_path) |
| config = { |
| "wrods_data": wrods_data, |
| "wrod_data_md5": wrod_data_md5 |
| } |
| self.write_id_config("data_list", "safety", "words", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "safety", "words", "backup_status", 1, conf["name"], msg="备份关键词:{}完成".format(conf["name"])) |
| self.print_log(config) |
| self.print_log("->>>备份关键词:{}完成".format(conf["name"])) |
|
|
| def backup_sqlite_data(self, conf): |
| self.print_log("->>>开始备份sqlite:{}".format(conf["name"])) |
| sqlite_path = conf["name"] |
| sqlite_data = None |
| sqlite_data_md5 = None |
| if os.path.exists(sqlite_path): |
| sqlite_data = self.copy_file(sqlite_path) |
| sqlite_data_md5 = self.get_md5(sqlite_path) |
| config = { |
| "sqlite_data": sqlite_data, |
| "sqlite_info": conf["name"], |
| "sqlite_data_md5": sqlite_data_md5 |
| } |
| self.write_id_config("data_list", "sql_list", "sqlite", config=config, sec_name=conf["name"]) |
| self.change_backup_status("data_list", "sql_list", "sqlite", "backup_status", 1, conf["name"], msg="备份sqlite:{}完成".format(conf["name"])) |
| self.print_log(config) |
| self.print_log("->>>备份sqlite:{}完成".format(conf["name"])) |
|
|
| |
| |
| |
|
|
| |
| def get_backup_record(self, id): |
| """ |
| 获取备份记录 |
| :param id: |
| :return: |
| """ |
| if id not in self.config: |
| return public.returnMsg(False, '任务不存在!') |
| if self.backup_record is None: |
| backup_log_path = self.config[id]["backup_log_path"] |
| res = json.loads(public.readFile(backup_log_path)) |
| self.backup_record = res |
|
|
| |
| def reduction(self, id): |
| """ |
| 还原 |
| :param id: |
| :return: |
| """ |
| if not isinstance(id, str): |
| id = id["id"] |
| conf = self.config[id] |
| self.get_backup_record(id) |
| reduction = json.loads(public.readFile(conf["reduction_task_config_path"]))["reduction_config"] |
| if not reduction: |
| self.print_log("还原信息不存在") |
| return public.returnMsg(False, '还原配置不存在') |
| if isinstance(reduction, str): |
| reduction = json.loads(reduction) |
| self.reduction_config = reduction |
| self.reduction_log_path = conf["reduction_log_path"] |
| |
| try: |
| backup_data_path = os.path.join(self.backup_path, id + "_backup.json") |
| self.backup_task_data = json.loads(public.readFile(backup_data_path)) |
| except: |
| pass |
| if not self.backup_task_data: |
| self.print_log("备份信息检查失败,恢复失败") |
| return public.returnMsg(False, '备份信息检查失败,恢复失败') |
|
|
| conf["status"] = 3 |
| self.status = 4 |
| conf["start_time"] = time.strftime('%Y-%m-%d %X') |
| self.write_config(id, conf) |
|
|
| |
| try: |
| if not os.path.exists(conf['backup_path'] + '.tar.gz'): |
| self.print_log("备份文件不存在") |
| return public.returnMsg(False, '备份文件不存在') |
| public.ExecShell('mkdir -p {}'.format(conf['backup_path'])) |
| public.ExecShell('tar -xzf {} -C {}'.format(conf['backup_path'] + '.tar.gz', conf['backup_path'])) |
| except: |
| pass |
| |
| self.reduction_env(self.reduction_config) |
| |
| self.reduction_data(self.reduction_config) |
| |
| |
| conf["status"] = self.status |
| conf['access_num'] = self.access_num |
| conf['error_num'] = self.error_num |
| self.write_config(id, conf) |
| return public.returnMsg(True, '还原结束') |
|
|
| |
| def change_reduction_status(self, block, name="", son_name="", status_name="", status=0, sec_name='', msg=''): |
| if status == 2: |
| self.status = 5 |
| self.error_num += 1 |
| if status == 1: |
| self.access_num += 1 |
| if sec_name != '': |
| for i in range(len(self.reduction_config[block][name][son_name])): |
| if self.reduction_config[block][name][son_name][i]['name'] == sec_name: |
| self.reduction_config[block][name][son_name][i][status_name] = status |
| if msg != '': |
| self.reduction_config[block][name][son_name][i]['msg'] = msg |
| elif son_name != "": |
| for i in range(len(self.reduction_config[block][name])): |
| if self.reduction_config[block][name][i]['name'] == son_name: |
| self.reduction_config[block][name][i][status_name] = status |
| if msg != '': |
| self.reduction_config[block][name][i]['msg'] = msg |
| elif name != "": |
| self.reduction_config[block][name][status_name] = status |
| if msg != '': |
| self.reduction_config[block][name]['msg'] = msg |
| else: |
| self.reduction_config[block][status_name] = status |
| if msg != '': |
| self.reduction_config[block]['msg'] = msg |
| public.writeFile(self.reduction_log_path, json.dumps(self.reduction_config)) |
|
|
| def reduction_env(self, conf): |
| env_conf = conf["env_list"] |
| connect = { |
| "php": self.reduction_php, |
| "mysql": self.reduction_mysql, |
| "mongo": self.reduction_mongo, |
| "redis": self.reduction_redis, |
| "pgsql": self.reduction_pgsql, |
| "nginx": self.reduction_nginx, |
| "apache": self.reduction_apache, |
| "ftp": self.reduction_ftp, |
| } |
| for k, v in env_conf.items(): |
| for i in v: |
| if i['status'] == 1: |
| |
| try: |
| connect[k](i) |
| except: |
| print(public.get_error_info()) |
| self.change_reduction_status("env_list", k, i["name"], "reduction_status", 2, msg="{}{}还原失败,程序出错".format(k, i["name"])) |
| else: |
| if i['status'] != 3 and i['name']: |
| self.change_reduction_status("env_list", k, i["name"], "reduction_status", 4, msg="{}{}未备份".format(k, i["name"])) |
|
|
| |
| def cehck_pid_status(self, pid): |
| try: |
| ps = psutil.Process(int(pid)) |
| return True |
| except: |
| return False |
|
|
| def reduction_php(self, conf): |
| self.print_log("->>>开始还原PHP环境:{}".format(conf["name"])) |
| self.change_reduction_status("env_list", "php", conf["name"], "reduction_status", -1, msg='开始还原php{}环境'.format(conf["name"])) |
| pid_file = '/www/server/php/{}/var/run/php-fpm.pid'.format(conf["name"]) |
| if conf["name"] == '52': |
| pid_file = '/www/server/php/{}/logs/php-fpm.pid'.format(conf["name"]) |
| php_backup_config = [j for i, j in self.backup_task_data['env_list']["php"].items() if i == conf["name"]] |
| if not php_backup_config or isinstance(php_backup_config, str): |
| self.print_log("获取php{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("env_list", "php", conf["name"], "reduction_status", 2, msg="获取php{}备份信息失败".format(conf["name"])) |
| return |
| php_backup_config = php_backup_config[0] |
| |
| php_path = '/www/server/php/{}'.format(conf["name"]) |
| if not os.path.exists(php_path): |
| self.print_log("php{}未安装,开始安装".format(conf["name"])) |
| |
| public.ExecShell('cd /www/server/panel/install && /bin/bash install_soft.sh 1 install php {}.{} &>> {}'.format(conf["name"][0], conf["name"][1], self.logs_file)) |
| self.print_log('php{}安装完成,检测安装状态中.....'.format(conf["name"])) |
| pid = public.readFile(pid_file) |
| if not self.cehck_pid_status(pid): |
| public.ExecShell('/etc/init.d/php-fpm-{} start'.format(conf["name"])) |
| time.sleep(0.1) |
| pid = public.readFile(pid_file) |
| if not self.cehck_pid_status(pid): |
| self.print_log('php{}安装失败'.format(conf["name"])) |
| self.change_reduction_status("env_list", "php", conf["name"], "reduction_status", 2, msg="php{}安装失败".format(conf["name"])) |
| public.ExecShell("rm -rf /www/server/php/{}".format(conf["name"])) |
| return |
| self.print_log('php{}安装完成'.format(conf["name"])) |
| else: |
| self.print_log('php{}已安装'.format(conf["name"])) |
| self.print_log('状态检测中.....') |
| pid = public.readFile(pid_file) |
| if not self.cehck_pid_status(pid): |
| self.print_log('php{}未启动,正在启动中......'.format(conf["name"])) |
| public.ExecShell('/etc/init.d/php-fpm-{} start'.format(conf["name"])) |
| time.sleep(0.1) |
| pid = public.readFile(pid_file) |
| self.print_log(pid) |
| if not self.cehck_pid_status(pid): |
| self.print_log('php{}启动失败'.format(conf["name"])) |
| self.change_reduction_status("env_list", "php", conf["name"], "reduction_status", 2, msg="php{}启动失败".format(conf["name"])) |
| return |
| self.print_log('php{}已启动'.format(conf["name"])) |
|
|
| |
| so_path = "/www/server/php/{}/lib/php/extensions/".format(conf["name"]) |
| if os.path.exists(so_path) and len(os.listdir(so_path)) > 0: |
| so_path = os.path.join(so_path, os.listdir(so_path)[0]) |
| development_list = php_backup_config["php_development"] |
| else: |
| development_list = [] |
| now_development_list = ajax.ajax().GetPHPConfig(public.to_dict_obj({"version": conf["name"]}))['libs'] |
| now_development_list = {i['name']: i for i in now_development_list} |
| install_err = [] |
| for development in development_list: |
| development = development.lower() |
| if development.lower() in now_development_list.keys() and now_development_list[development.lower()]["status"] != True and conf["name"] in now_development_list[development.lower()][ |
| "versions"] and not os.path.exists(os.path.join(so_path, "{}.so".format(development))): |
| self.print_log("开始安装php{}拓展:{}".format(conf["name"], development)) |
| public.ExecShell( |
| 'wget -O {sh_name}.sh https://download.bt.cn/install/1/{sh_name}.sh && sh {sh_name}.sh install {php_version} $>> {log}'.format(sh_name=development.lower(), |
| php_version=conf["name"], |
| log=self.logs_file)) |
| |
| if 'swoole' in development: |
| development = 'swoole' |
| res = public.ExecShell('/www/server/php/{}/bin/php -m'.format(conf["name"])) |
| if development in res[0].lower() and "{}.so".format(development) in os.listdir(so_path): |
| self.print_log("php{}拓展:{}安装成功".format(conf["name"], development)) |
| else: |
| self.print_log("php{}拓展:{}安装失败".format(conf["name"], development)) |
| install_err.append(development) |
| |
| for development in install_err: |
| development = development.lower() |
| self.print_log("开始安装php{}拓展:{}".format(conf["name"], development)) |
| public.ExecShell( |
| 'wget -O {sh_name}.sh https://download.bt.cn/install/1/{sh_name}.sh && sh {sh_name}.sh install {php_version} $>> {log}'.format(sh_name=development.lower(), php_version=conf["name"], |
| log=self.logs_file)) |
| |
| if 'swoole' in development: |
| development = 'swoole' |
| res = public.ExecShell('/www/server/php/{}/bin/php -m'.format(conf["name"])) |
| try: |
| if development in res[0].lower() or "{}.so".format(development) in os.listdir(so_path): |
| self.print_log("php{}拓展:{}安装成功".format(conf["name"], development)) |
| else: |
| self.print_log("php{}拓展:{}安装失败".format(conf["name"], development)) |
| except: |
| pass |
| |
| php_ini_path = '/www/server/php/{}/etc/php.ini'.format(conf["name"]) |
| php_fpm_path = '/www/server/php/{}/etc/php-fpm.conf'.format(conf["name"]) |
| php_ini_res = self.uncopy_file(php_backup_config["php_ini"], php_ini_path, isfile=True) |
| php_fpm_res = self.uncopy_file(php_backup_config["php_fpm"], php_fpm_path, isfile=True) |
| if not php_ini_res or not php_fpm_res: |
| self.print_log("还原php{}配置文件失败".format(conf["name"])) |
| self.change_reduction_status("env_list", "php", conf["name"], "reduction_status", 2, msg="还原php{}配置文件失败".format(conf["name"])) |
| return |
| |
| if not os.path.exists(so_path) or 'security_notice.so' not in os.listdir(so_path): |
| public.ExecShell("sed -i '/security_notice/ s/.*/ /' {}".format(php_ini_path)) |
| public.ExecShell("sed -i '/security.notice/ s/.*/ /' {}".format(php_fpm_path)) |
| self.print_log("还原php{}配置文件完成".format(conf["name"])) |
| |
| public.ExecShell('/etc/init.d/php-fpm-{} reload'.format(conf["name"])) |
| self.print_log("->>>还原PHP环境:{}完成".format(conf["name"])) |
| self.change_reduction_status("env_list", "php", conf["name"], "reduction_status", 1, msg="还原php{}配置文件完成".format(conf["name"])) |
|
|
| def reduction_mysql(self, conf): |
| self.print_log("->>>开始还原mysql环境:{}".format(conf["name"])) |
| self.print_log(conf) |
| backup_mysql_conf = self.backup_task_data['env_list']['mysql'] |
| self.change_reduction_status("env_list", "mysql", conf['name'], status_name="reduction_status", status=-1, msg="开始还原mysql{}环境".format(conf["name"])) |
| self.print_log(backup_mysql_conf) |
| |
| mysql_path = '/www/server/mysql/version.pl' |
| if not os.path.exists(mysql_path): |
| self.print_log("mysql未安装,开始安装mysql{}".format(backup_mysql_conf["version"])) |
| public.ExecShell('mkdir -p /www/server/mysql') |
| version = backup_mysql_conf["version"] |
| if version.count('.') > 1: |
| version = version.split('.')[:2] |
| version = '.'.join(version) |
| public.ExecShell("/bin/bash /www/server/panel/install/install_soft.sh 1 install mysql {} &>> {}".format(version, self.logs_file)) |
| mysql_version = public.readFile('/www/server/mysql/version.pl') |
| if not mysql_version: |
| self.print_log("mysql读取版本异常,请手动检查") |
| self.change_reduction_status("env_list", "mysql", conf['name'], status_name="reduction_status", status=2, msg="mysql读取版本异常,请手动检查") |
| else: |
| mysql_version = mysql_version.strip() |
| if mysql_version != conf["name"]: |
| self.print_log("mysql版本不一致,请手动操作将mysql版本升级到{}版本".format(conf["name"])) |
| self.change_reduction_status("env_list", "mysql", conf['name'], status_name="reduction_status", status=2, msg="mysql版本不一致,请手动操作将mysql版本升级到{}版本".format(conf["name"])) |
| return |
| else: |
| self.print_log("mysql版本一致") |
| |
| self.print_log('开始恢复mysql配置文件') |
| config_path = '/etc/my.cnf' |
| res = self.uncopy_file(backup_mysql_conf["mysql_conf"], config_path, isfile=True, md5=backup_mysql_conf["mysql_conf_md5"]) |
| if not res: |
| self.change_reduction_status("env_list", "mysql", conf['name'], status_name="reduction_status", status=2, msg="还原mysql{}配置文件失败".format(conf["name"])) |
| self.print_log("->>>还原mysql环境:{}完成".format(conf["name"])) |
| self.change_reduction_status("env_list", "mysql", conf['name'], status_name="reduction_status", status=1, msg="还原mysql{}完成".format(conf["name"])) |
|
|
| def reduction_mongo(self, conf): |
| self.print_log("->>>开始还原mongo环境:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原mongo环境:{}完成".format(conf["name"])) |
|
|
| def reduction_redis(self, conf): |
| self.print_log("->>>开始还原redis环境:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原redis环境:{}完成".format(conf["name"])) |
|
|
| def reduction_pgsql(self, conf): |
| self.print_log("->>>开始还原pgsql环境:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原pgsql环境:{}完成".format(conf["name"])) |
|
|
| def reduction_nginx(self, conf): |
| self.print_log("->>>开始还原nginx环境:{}".format(conf["name"])) |
| |
| |
| self.change_reduction_status("env_list", "nginx", conf['name'], status_name="reduction_status", status=-1, msg="开始还原nginx环境") |
| nginx_path = '/www/server/nginx' |
| |
| if os.path.exists(nginx_path): |
| public.ExecShell("/etc/init.d/nginx stop") |
| self.print_log('关闭nginx服务') |
| self.print_log("开始恢复nginx") |
| flag = 1 |
| |
| res = self.uncopy_file(self.backup_task_data['env_list']['nginx']["nginx_file"], "/www/server/nginx/", unbak=True) |
| if not res: |
| flag = 0 |
| |
| if self.backup_task_data['env_list']['nginx']["nginx_cmd"]: |
| res = self.uncopy_file(self.backup_task_data['env_list']['nginx']["nginx_cmd"], "/etc/init.d/nginx", isfile=True, md5=self.backup_task_data['env_list']['nginx']["nginx_cmd_md5"]) |
| if not res: |
| flag = 0 |
| if self.backup_task_data['env_list']['nginx']["nginx_systemd"]: |
| res = self.uncopy_file(self.backup_task_data['env_list']['nginx']["nginx_systemd"], "/lib/systemd/system/nginx.service", isfile=True, |
| md5=self.backup_task_data['env_list']['nginx']["nginx_systemd_md5"]) |
| if not res: |
| flag = 0 |
| if not flag: |
| |
| if os.path.exists("/www/server/nginx_bak"): |
| public.ExecShell("rm -rf /www/server/nginx") |
| public.ExecShell("mv /www/server/nginx_bak /www/server/nginx") |
| if os.path.exists("/etc/init.d/nginx_bak"): |
| public.ExecShell("rm -rf /etc/init.d/nginx") |
| public.ExecShell("mv /etc/init.d/nginx_bak /etc/init.d/nginx") |
| if os.path.exists("/lib/systemd/system/nginx.service_bak"): |
| public.ExecShell("rm -rf /lib/systemd/system/nginx.service") |
| public.ExecShell("mv /lib/systemd/system/nginx.service_bak /lib/systemd/system/nginx.service") |
| self.change_reduction_status("env_list", "nginx", conf['name'], status_name="reduction_status", status=2, msg="还原nginx失败") |
| public.ExecShell('/etc/init.d/nginx start') |
| self.print_log("还原nginx失败") |
| return |
| |
| public.ExecShell("/etc/init.d/nginx start") |
| self.change_reduction_status("env_list", "nginx", conf['name'], status_name="reduction_status", status=1, msg="还原nginx完成") |
| self.print_log("->>>还原nginx环境:{}完成".format(conf["name"])) |
|
|
| def reduction_apache(self, conf): |
| self.print_log("->>>开始还原apache环境:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.change_reduction_status("env_list", "apache", conf['name'], status_name="reduction_status", status=-1, msg="开始还原apache{}环境".format(conf["name"])) |
| self.print_log(self.backup_task_data['env_list']['apache']) |
| apache_path = '/www/server/apache/version.pl' |
| if not os.path.exists(apache_path): |
| |
| public.ExecShell('mkdir -p /www/server/apache') |
| version = self.backup_task_data['env_list']['apache']["version"] |
| if version.count('.') > 1: |
| version = version.split('.')[:2] |
| version = '.'.join(version) |
| public.ExecShell("/bin/bash /www/server/panel/install/install_soft.sh 1 install apache {} &>> {}".format(version, self.logs_file)) |
| apache_version = public.readFile('/www/server/apache/version.pl') |
| if not apache_version: |
| self.print_log("apache读取版本异常,请手动检查") |
| self.change_reduction_status("env_list", "apache", conf['name'], status_name="reduction_status", status=2, msg="apache读取版本异常,请手动检查") |
| else: |
| apache_version = apache_version.strip() |
| if apache_version != conf["name"]: |
| public.ExecShell('rm -rf /www/server/apache') |
| self.print_log('apache版本不一致,升级apache到{}版本'.format(conf["name"])) |
| version = conf["name"] |
| if version.count('.') > 1: |
| version = version.split('.')[:2] |
| version = '.'.join(version) |
| public.ExecShell("/bin/bash /www/server/panel/install/install_soft.sh 1 install apache {} &>> {}".format(version, self.logs_file)) |
| |
| res = self.uncopy_file(self.backup_task_data['env_list']['apache']["apache_conf"], "/www/server/apache/", isfile=True, md5=self.backup_task_data['env_list']['apache']["apache_conf_md5"]) |
| if not res: |
| self.change_reduction_status("env_list", "apache", conf['name'], status_name="reduction_status", status=2, msg="还原apache{}配置文件失败".format(conf["name"])) |
| self.print_log("->>>还原apache环境:{}完成".format(conf["name"])) |
|
|
| def reduction_ftp(self, conf): |
| self.print_log("->>>开始还原ftp环境:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.change_reduction_status("env_list", "ftp", conf['name'], status_name="reduction_status", status=-1, msg="开始还原ftp{}环境".format(conf["name"])) |
| self.print_log(self.backup_task_data['env_list']['ftp']) |
| |
| ftp_path = '/www/server/pure-ftpd' |
| if not os.path.exists(ftp_path): |
| |
| version = self.backup_task_data['env_list']['ftp']["version"] |
| public.ExecShell("/bin/bash /www/server/panel/install/install_soft.sh 1 install pure-ftpd {}&>> {}".format(version, self.logs_file)) |
| |
| self.print_log('开始恢复ftp配置文件') |
| res = self.uncopy_file(self.backup_task_data['env_list']['ftp']["ftp_conf"], "/www/server/pure-ftpd/etc/pure-ftpd.conf", md5=self.backup_task_data['env_list']['ftp']["ftp_conf_md5"]) |
| if not res: |
| self.change_reduction_status("env_list", "ftp", conf['name'], status_name="reduction_status", status=2, msg="还原ftp{}配置文件失败".format(conf["name"])) |
| |
| public.ExecShell('rm -rf /www/server/pure-ftpd') |
| public.ExecShell('mv /www/server/pure-ftpd/etc/pure-ftpd.conf_bak /www/server/pure-ftpd/etc/pure-ftpd.conf') |
| |
| self.print_log('开始检查ftp日志开启状态') |
| rsyslog_path = "/etc/rsyslog.conf" |
| cofig = public.readFile(rsyslog_path) |
| if "ftp.*" in cofig: |
| log_status = 1 |
| else: |
| log_status = 0 |
| if self.backup_task_data['env_list']['ftp']["log_status"] != log_status: |
| if self.backup_task_data['env_list']['ftp']["log_status"]: |
| public.ExecShell("sed -i '/ftp\.\*/d' {}".format(rsyslog_path)) |
| else: |
| public.ExecShell("echo 'ftp.* /var/log/pureftpd.log' >> {}".format(rsyslog_path)) |
| public.ExecShell('/etc/init.d/rsyslog restart') |
| self.print_log('ftp日志开启状态恢复完成') |
| self.change_reduction_status("env_list", "ftp", conf['name'], status_name="reduction_status", status=1, msg="还原ftp{}完成".format(conf["name"])) |
| self.print_log("->>>还原ftp环境:{}完成".format(conf["name"])) |
|
|
| def reduction_data(self, conf): |
| data_conf = conf["data_list"] |
| connect = { |
| "php": self.reduction_php_data, |
| "java": self.reduction_java_data, |
| "node": self.reduction_node_data, |
| "python": self.reduction_python_data, |
| "other": self.reduction_other_data, |
| "net": self.reduction_net_data, |
| "proxy": self.reduction_proxy_data, |
| "html": self.reduction_html_data, |
| "mysql": self.reduction_mysql_data, |
| "mongodb": self.reduction_mongodb_data, |
| "redis": self.reduction_redis_data, |
| "pgsql": self.reduction_pgsql_data, |
| "ftp_list": self.reduction_ftp_data, |
| "terminal_list": self.reduction_terminal_data, |
| "crontab_list": self.reduction_crontab_data, |
| "port_list": self.reduction_port_data, |
| "ip_list": self.reduction_ip_data, |
| "port_redirect": self.reduction_port_redirect_data, |
| "area_list": self.reduction_area_data, |
| "ssh_config": self.reduction_ssh_config_data, |
| "words": self.reduction_words_data, |
| "sqlite": self.reduction_sqlite_data, |
| } |
| for k, v in data_conf.items(): |
| if k in ['site_list', 'sql_list', 'config_list', "safety"]: |
| for type, dates in v.items(): |
| if type not in connect.keys(): |
| pass |
| for data in dates: |
| if int(data['status']) in [1, -1, 2] and data['backup_status'] == 1: |
| try: |
| connect[type.lower()](data) |
| except: |
| print(public.get_error_info()) |
| self.change_reduction_status("data_list", k, type, "reduction_status", 2, data["name"], msg="{}还原失败,程序出错".format(data["name"])) |
| else: |
| self.change_reduction_status("data_list", k, type, "reduction_status", 4, data["name"], msg="{}备份状态异常".format(data["name"])) |
| elif k in ['ftp_list']: |
| for i in v: |
| if i['status'] in [1, -1, 2] and i['backup_status'] == 1: |
| try: |
| connect[k](i) |
| except: |
| print(public.get_error_info()) |
| self.change_reduction_status("data_list", "ftp_list", i["name"], "reduction_status", 2, msg="{}还原失败,程序出错".format(i["name"])) |
| else: |
| self.change_reduction_status("data_list", "ftp_list", i["name"], "reduction_status", 4, msg="{}备份状态异常".format(i["name"])) |
| else: |
| for j in v: |
| if j['status'] in [1, -1, 2] and j['backup_status'] == 1: |
| try: |
| connect[k](j) |
| except: |
| print(public.get_error_info()) |
| self.change_reduction_status("data_list", k, j["name"], "reduction_status", 2, msg="{}还原失败,程序出错".format(j["name"])) |
| else: |
| if j['status'] != 3 and j['name']: |
| self.change_reduction_status("data_list", k, j["name"], "reduction_status", 4, msg="{}备份状态异常".format(j["name"])) |
|
|
| def reduction_php_data(self, conf): |
| self.print_log(")->>>开始还原PHP数据:{}".format(conf["name"])) |
| backup_conf_config = self.backup_task_data.get('data_list', {}).get('site_list', {}).get('php', {}).get(conf['name'], {}) |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", -1, conf["name"], msg="开始还原php{}数据".format(conf["name"])) |
| if not backup_conf_config: |
| self.print_log("获取php{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="获取php{}备份信息失败".format(conf["name"])) |
| return |
| |
| now_site_config = public.M('sites').where('name=?', (conf['name'],)).select() |
| site_info = backup_conf_config["site_info"] |
| |
| import panelSite |
| from mod.project.php.php_asyncMod import main as php_asyncMod |
| is_phpmod = False |
| if 'project_config' in site_info.keys(): |
| site_info['project_config'] = json.loads(site_info['project_config']) |
| if 'type' in site_info['project_config'].keys() and site_info['project_config']['type'].lower() == 'phpmod': |
| is_phpmod = True |
| if now_site_config and isinstance(now_site_config, list): |
| |
| now_site_config = now_site_config[0] |
| site_info['ps'] = now_site_config['ps'] |
| site_info['id'] = now_site_config['id'] |
| site_info.pop('index') |
| if isinstance(site_info.get('project_config', ''), dict): |
| site_info['project_config'] = json.dumps(site_info['project_config']) |
| site_info.pop('php_version') |
| public.M('sites').where('name=? and id=?', (site_info["name"], now_site_config["id"])).update(site_info) |
| else: |
| if not is_phpmod: |
| args = public.dict_obj() |
| args.path = site_info['path'] |
| args.ftp = False |
| args.type = 'PHP' |
| args.type_id = site_info['type_id'] |
| args.ps = site_info['ps'] |
| args.port = '80' |
| args.version = site_info['php_version'] |
| args.need_index = 0 |
| args.need_404 = 0 |
| args.sql = False |
| args.codeing = 'utf8mb4' |
| args.webname = json.dumps({"domain": site_info['name'], "domainlist": [], "count": 0}) |
| panelSite.panelSite().AddSite(args) |
| else: |
| args = public.dict_obj() |
| args.site_path = site_info['path'] |
| args.project_cmd = site_info['project_config']['start_cmd'] |
| args.install_dependence = '0' |
| args.php_version = site_info['project_config']['php_version'] |
| args.sql = False |
| args.project_ps = site_info['ps'] |
| args.project_port = '' |
| args.open_proxy = '0' |
| args.project_proxy_path = '' |
| args.run_user = site_info['project_config']['run_user'] |
| args.composer_version = '' |
| args.webname = json.dumps({"domain": site_info['name'], "domainlist": [], "count": 0}) |
| php_asyncMod().create_project(args) |
|
|
| self.print_log('面板网站存储信息同步完成') |
|
|
| |
| site_path = site_info['path'] |
| res = self.uncopy_file(backup_conf_config["site_file"], site_path, isfile=False, unbak=True) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="还原php{}网站文件失败".format(conf["name"])) |
| self.print_log("还原php{}网站文件失败".format(conf["name"])) |
| return |
|
|
| |
| site_id = public.M('sites').where('name=?', (conf['name'],)).getField('id') |
| domains = backup_conf_config["domains"] |
| if domains and isinstance(domains, list): |
| domains = {i["name"]: i for i in domains} |
| sql = public.M('domain') |
| now_domains = sql.where('pid=?', (site_id,)).select() |
| if now_domains and isinstance(now_domains, list): |
| now_domains = {i["name"]: i for i in now_domains} |
| else: |
| now_domains = {} |
|
|
| print(domains) |
| print(now_domains) |
| |
| del_domains = [i for i in now_domains.keys() if i not in domains.keys()] |
| if del_domains: |
| public.M('domain').where('name in (?)', (','.join(del_domains))).delete() |
| self.print_log('删除多余的域名成功:{}'.format(','.join(del_domains))) |
| |
| for domain, value in domains.items(): |
| if domain not in now_domains.keys(): |
| self.print_log('添加域名:{}'.format(domain)) |
| value.pop('id') |
| value['pid'] = site_id |
| public.M('domain').insert(value) |
| else: |
| domains[domain].pop('id') |
| value['pid'] = site_id |
| public.M('domain').where('name=?', (domain,)).update(value) |
|
|
| self.print_log("php{}网站域名恢复完成".format(conf["name"])) |
|
|
| |
| self.print_log('开始恢复php{}网站nginx和apache配置文件'.format(conf["name"])) |
| nginx_conf_path = '/www/server/panel/vhost/nginx/{}.conf'.format(conf["name"]) |
| apache_conf_path = '/www/server/panel/vhost/apache/{}.conf'.format(conf["name"]) |
| if backup_conf_config['nginx_config'] and os.path.exists(backup_conf_config['nginx_config']): |
| res = self.uncopy_file(backup_conf_config["nginx_config"], nginx_conf_path, isfile=True, md5=backup_conf_config["nginx_config_md5"]) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="还原php{}nginx配置文件失败".format(conf["name"])) |
| self.print_log("还原php{}nginx配置文件失败".format(conf["name"])) |
| return |
| if backup_conf_config['apache_config'] and os.path.exists(backup_conf_config['apache_config']): |
| res = self.uncopy_file(backup_conf_config["apache_config"], apache_conf_path, isfile=True, md5=backup_conf_config["apache_config_md5"]) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="还原php{}apache配置文件失败".format(conf["name"])) |
| self.print_log("还原php{}apache配置文件失败".format(conf["name"])) |
| return |
| self.print_log("php{}网站nginx和apache配置文件恢复完成".format(conf["name"])) |
|
|
| |
| self.print_log('开始恢复php{}网站重定向'.format(conf["name"])) |
| redirect_list = backup_conf_config["redirect_list"] |
| __redirectfile = "/www/server/panel/data/redirect.conf" |
| redirectconf = json.loads(public.readFile(__redirectfile)) |
| red_name = {j['sitename']: i for i, j in enumerate(redirectconf)} |
| for i in redirect_list: |
| if i["sitename"] not in red_name.keys(): |
| redirectconf.append(i) |
| elif i['sitename'] in red_name.keys(): |
| redirectconf[red_name[i['sitename']]] = i |
| public.writeFile(__redirectfile, json.dumps(redirectconf)) |
| res_nginx = self.uncopy_file(backup_conf_config["redirect_nginx_data"], '/www/server/panel/vhost/nginx/redirect/{}'.format(conf["name"]), isfile=False) |
| res_apache = self.uncopy_file(backup_conf_config["redirect_apache_data"], '/www/server/panel/vhost/apache/redirect/{}'.format(conf["name"]), isfile=False) |
| if res_nginx and res_apache: |
| self.print_log("恢复重定向成功") |
| else: |
| self.print_log("恢复重定向失败") |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="恢复重定向失败") |
| |
| old_list = [i['redirectname'] for i in redirect_list] |
| now_redirect_list = [i['redirectname'] for i in redirectconf if i['sitename'] == conf["name"]] |
| for redirect in now_redirect_list: |
| if redirect not in old_list: |
| if is_phpmod: |
| res = php_asyncMod().remove_project_redirect(public.to_dict_obj({"sitename": conf["name"], "redirectname": redirect})) |
| else: |
| res = panelSite.panelSite().DeleteRedirect(public.to_dict_obj({"siteName": conf["name"], "redirectName": redirect})) |
| if res['status']: |
| self.print_log("删除多余重定向:{}成功".format(redirect)) |
| else: |
| self.print_log("删除多余重定向:{}失败".format(redirect)) |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="删除多余重定向:{}失败".format(redirect)) |
| self.print_log("php{}网站重定向恢复完成".format(conf["name"])) |
|
|
| |
| self.print_log('开始恢复php{}网站反向代理'.format(conf["name"])) |
| proxy_list = backup_conf_config["proxy_list"] |
| if not is_phpmod: |
| __proxyfile = '{}/data/proxyfile.json'.format(public.get_panel_path()) |
|
|
| else: |
| __proxyfile = "{}/data/mod_proxy_file.conf".format(public.get_panel_path()) |
| try: |
| proxyUrl = json.loads(public.readFile(__proxyfile)) |
| except: |
| proxyUrl = {} |
| proxy_name = {j['sitename']: i for i, j in enumerate(proxyUrl)} |
| for i in proxy_list: |
| if i["sitename"] not in proxy_name.keys(): |
| proxyUrl.append(i) |
| elif i['sitename'] in proxy_name.keys(): |
| proxyUrl[proxy_name[i['sitename']]] = i |
|
|
| public.writeFile(__proxyfile, json.dumps(proxyUrl)) |
| res_n = self.uncopy_file(backup_conf_config["proxy_nginx_data"], '/www/server/panel/vhost/nginx/proxy/{}'.format(conf["name"]), isfile=False) |
| res_a = self.uncopy_file(backup_conf_config["proxy_apache_data"], '/www/server/panel/vhost/apache/proxy/{}'.format(conf["name"]), isfile=False) |
| if not res_n or not res_a: |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="恢复nginx反向代理失败") |
| self.print_log("恢复反向代理失败") |
|
|
| |
| old_list = [i['proxyname'] for i in proxy_list] |
| proxy_name = [i for i in proxyUrl if i['sitename'] == conf["name"]] |
| for proxy in proxy_name: |
| if proxy['proxyname'] not in old_list: |
| if is_phpmod: |
| res = php_asyncMod().remove_proxy(public.to_dict_obj({"sitename": conf["name"], "proxyname": proxy['proxyname']})) |
| else: |
| res = panelSite.panelSite().DeleteProxy(public.to_dict_obj({"siteName": conf["name"], "proxyName": proxy['proxyname']})) |
| if not res['status']: |
| self.print_log("删除多余反向代理:{}失败".format(proxy['proxyname'])) |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="删除多余反向代理:{}失败".format(proxy['proxyname'])) |
| return |
| self.print_log("删除多余反向代理:{}成功".format(proxy['proxyname'])) |
|
|
| self.print_log("php{}网站反向代理恢复完成".format(conf["name"])) |
|
|
| |
| self.print_log('开始恢复php{}网站ssl证书'.format(conf["name"])) |
| if backup_conf_config["ssl_info"]: |
| ssl_path = '/www/server/panel/vhost/cert/{}'.format(conf["name"]) |
| res = self.uncopy_file(backup_conf_config["ssl_info"], ssl_path, isfile=False) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="还原php{}ssl证书失败".format(conf["name"])) |
| self.print_log("还原php{}ssl证书失败".format(conf["name"])) |
| return |
| self.print_log("php{}网站ssl证书恢复完成".format(conf["name"])) |
| else: |
| self.print_log("php{}网站无ssl证书".format(conf["name"])) |
|
|
| |
| self.print_log('开始恢复php{}网站目录加密访问'.format(conf["name"])) |
| if backup_conf_config["dir_auth_json"]: |
| dir_auth_path = '/tmp/{}'.format(conf["name"]) |
| self.uncopy_file(backup_conf_config["dir_auth_json"], dir_auth_path, unbak=True) |
| if os.path.exists(dir_auth_path): |
| res = public.readFile(dir_auth_path) |
| if res: |
| res = json.loads(res) |
| data = res.get(conf["name"], []) |
| if data: |
| config_path = '/www/server/panel/data/site_dir_auth.json' |
| if os.path.exists(config_path): |
| res = public.readFile(config_path) |
| if res: |
| res = json.loads(res) |
| else: |
| res = {} |
| res[conf["name"]] = data |
| public.writeFile(config_path, json.dumps(res)) |
| else: |
| conf = {conf["name"]: data} |
| public.writeFile(config_path, json.dumps(conf)) |
| if backup_conf_config["dir_auth_file"]: |
| res = self.uncopy_file(backup_conf_config["dir_auth_file"], '/www/server/panel/vhost/nginx/dir_auth/{}'.format(conf["name"]), isfile=False) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="还原php{}目录加密访问失败".format(conf["name"])) |
| self.print_log("还原php{}目录加密访问失败".format(conf["name"])) |
| return |
| self.print_log("php{}网站目录加密访问恢复完成".format(conf["name"])) |
|
|
| |
| if backup_conf_config["banding"]: |
| if is_phpmod: |
| pass |
| else: |
| self.print_log('开始恢复php{}网站子目录域名绑定'.format(conf["name"])) |
| res = panelSite.panelSite().GetDirBinding(public.to_dict_obj({"id": site_id})) |
| banding_list = res["binding"] |
| banding_list = {i["domain"]: i for i in banding_list} |
| old_list = {i["domain"]: i for i in backup_conf_config["banding"]} |
| for k, v in old_list.items(): |
| if k not in banding_list.keys(): |
| res = panelSite.panelSite().AddDirBinding(public.to_dict_obj({"id": site_id, "domain": v["domain"], "dirName": v["path"]})) |
| if not res["status"]: |
| self.print_log("恢复子目录域名绑定:{}失败".format(k)) |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="恢复子目录域名绑定:{}失败".format(k)) |
| return |
| self.print_log("恢复子目录域名绑定:{}成功".format(k)) |
| for k, v in banding_list.items(): |
| if k not in old_list.keys(): |
| res = panelSite.panelSite().DelDirBinding(public.to_dict_obj({"id": v['id']})) |
| if not res["status"]: |
| self.print_log("删除多余子目录域名绑定:{}失败".format(k)) |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="删除多余子目录域名绑定:{}失败".format(k)) |
| return |
| self.print_log("删除多余子目录域名绑定:{}成功".format(k)) |
| |
| if backup_conf_config["pseudo_static_data"]: |
| self.print_log('开始恢复php{}网站伪静态'.format(conf["name"])) |
| res = self.uncopy_file(backup_conf_config["pseudo_static_data"], '/www/server/panel/vhost/rewrite/{}.conf'.format(conf["name"]), isfile=True, |
| md5=backup_conf_config["pseudo_static_data_md5"]) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 2, conf["name"], msg="还原php{}伪静态失败".format(conf["name"])) |
| self.print_log("还原php{}伪静态失败".format(conf["name"])) |
| return |
| self.print_log("php{}网站伪静态恢复完成".format(conf["name"])) |
| |
| self.print_log('开始还原php{}网站相关数据库'.format(conf["name"])) |
| if backup_conf_config["database_info"]: |
| self.reduction_mysql_data(backup_conf_config['database_info']) |
|
|
| if backup_conf_config["ftp_info"]: |
| self.reduction_ftp_data(backup_conf_config["ftp_info"]) |
| self.print_log('php{}网站相关数据库恢复完成'.format(conf["name"])) |
|
|
| self.print_log("->>>还原PHP数据:{}完成".format(conf["name"])) |
| self.change_reduction_status("data_list", "site_list", "php", "reduction_status", 1, conf["name"], msg="还原成功!") |
|
|
| def reduction_java_data(self, conf): |
| self.print_log("->>>开始还原java数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原java数据:{}完成".format(conf["name"])) |
|
|
| def reduction_node_data(self, conf): |
| self.print_log("->>>开始还原node数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原node数据:{}完成".format(conf["name"])) |
|
|
| def reduction_python_data(self, conf): |
| self.print_log("->>>开始还原python数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原python数据:{}完成".format(conf["name"])) |
|
|
| def reduction_other_data(self, conf): |
| self.print_log("->>>开始还原other数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原other数据:{}完成".format(conf["name"])) |
|
|
| def reduction_net_data(self, conf): |
| self.print_log("->>>开始还原net数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原net数据:{}完成".format(conf["name"])) |
|
|
| def reduction_proxy_data(self, conf): |
| self.print_log("->>>开始还原proxy数据:{}".format(conf["name"])) |
| self.change_reduction_status("data_list", "site_list", "proxy", "reduction_status", -1, conf["name"], msg="开始还原proxy{}数据".format(conf["name"])) |
| proxy_config_path = "/www/server/proxy_project/sites/{}".format(conf["name"]) |
| nginx_config_path = "/www/server/panel/vhost/nginx/{}.conf".format(conf["name"]) |
| apache_config_path = "/www/server/panel/vhost/apache/{}.conf".format(conf["name"]) |
| |
| self.print_log('开始恢复数据库存储信息proxy:{}'.format(conf["name"])) |
| site_info = self.backup_task_data['data_list']['site_list']['proxy'].get(conf["name"], {}) |
| if not site_info: |
| self.print_log("获取proxy{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "site_list", "proxy", "reduction_status", 2, conf["name"], msg="获取proxy{}备份信息失败") |
| return |
| site_db_info = site_info["site_info"][0] |
| now_site_info = public.M('sites').where('name=?', (conf["name"],)).select() |
| if now_site_info and not isinstance(now_site_info, str): |
| now_site_info = now_site_info[0] |
| site_db_info.pop('id') |
| now_site_info.update(site_db_info) |
| now_site_info.pop('index') |
| public.M('sites').where('name=? and project_type="proxy"', (conf["name"],)).update(now_site_info) |
| else: |
| proxy_cache_dir = "/www/wwwroot/{}/proxy_cache_dir".format(conf["name"]) |
| if not os.path.exists(proxy_cache_dir): |
| public.ExecShell('mkdir -p {}'.format(proxy_cache_dir)) |
| if os.path.exists(proxy_cache_dir): |
| public.ExecShell('chown -R www:www {}'.format(proxy_cache_dir)) |
| public.ExecShell('chmod -R 755 {}'.format(proxy_cache_dir)) |
| self.print_log('创建proxy{}缓存目录成功'.format(conf["name"])) |
| else: |
| self.print_log('创建proxy{}缓存目录失败'.format(conf["name"])) |
| self.change_reduction_status("data_list", "site_list", "proxy", "reduction_status", 2, conf["name"], msg="创建proxy{}缓存目录失败{}".format(conf["name"], proxy_cache_dir)) |
| return |
| site_db_info.pop('id') |
| site_db_info['project_type'] = 'proxy' |
| site_db_info.pop('index') |
| public.M('sites').insert(site_db_info) |
| self.print_log('面板网站存储信息同步完成') |
| |
| self.print_log('开始恢复proxy{}网站配置文件'.format(conf["name"])) |
| res = self.uncopy_file(site_info["proxy_config"], proxy_config_path, isfile=True, md5=site_info["proxy_config_md5"]) |
| if not res: |
| self.print_log('还原proxy{}配置文件失败'.format(conf["name"])) |
| self.change_reduction_status("data_list", "site_list", "proxy", "reduction_status", 2, conf["name"], msg="还原proxy{}配置文件失败".format(conf["name"])) |
| return |
| self.print_log('proxy{}网站配置文件恢复完成'.format(conf["name"])) |
|
|
| |
| self.print_log('开始恢复proxy{}网站nginx和apache配置文件'.format(conf["name"])) |
| if site_info['nginx_config'] and os.path.exists(site_info['nginx_config']): |
| res = self.uncopy_file(site_info["nginx_config"], nginx_config_path, isfile=True, md5=site_info["nginx_config_md5"]) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "proxy", "reduction_status", 2, conf["name"], msg="还原proxy{}nginx配置文件失败".format(conf["name"])) |
| self.print_log("还原proxy{}nginx配置文件失败".format(conf["name"])) |
| return |
| if site_info['apache_config'] and os.path.exists(site_info['apache_config']): |
| res = self.uncopy_file(site_info["apache_config"], apache_config_path, isfile=True, md5=site_info["apache_config_md5"]) |
| if not res: |
| self.change_reduction_status("data_list", "site_list", "proxy", "reduction_status", 2, conf["name"], msg="还原proxy{}apache配置文件失败".format(conf["name"])) |
| self.print_log("还原proxy{}apache配置文件失败".format(conf["name"])) |
| return |
| self.print_log('proxy{}网站nginx和apache配置文件恢复完成'.format(conf["name"])) |
| self.print_log("->>>还原proxy数据:{}完成".format(conf["name"])) |
| self.change_reduction_status("data_list", "site_list", "proxy", "reduction_status", 1, conf["name"], msg="还原成功!") |
|
|
| def reduction_html_data(self, conf): |
| self.print_log("->>>开始还原html数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原html数据:{}完成".format(conf["name"])) |
|
|
| def reduction_mysql_data(self, conf): |
| self.print_log("->>>开始还原mysql数据:{}".format(conf["name"])) |
| bakup_config = self.backup_task_data['data_list']['sql_list']['mysql'].get(conf['name'], {}) |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", -1, conf["name"], msg="开始还原mysql{}数据".format(conf["name"])) |
| if not bakup_config: |
| self.print_log("获取mysql{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", 2, conf["name"], msg="获取mysql{}备份信息失败".format(conf["name"])) |
| return |
|
|
| if int(bakup_config['mysql_info']['db_type']) == 2: |
| |
| self.print_log('开始还原mysql{}远程数据库配置'.format(conf["name"])) |
| cloud_server = bakup_config['cloud_server'] |
| now_cloud_server = public.M('database_servers').where('id=?', (bakup_config['mysql_info']['sid'])).select() |
| if not now_cloud_server: |
| public.M('database_servers').insert(cloud_server) |
| else: |
| cloud_server.pop('id') |
| public.M('database_servers').where('id=?', (bakup_config['mysql_info']['sid'])).update(cloud_server) |
| now_db_info = public.M('databases').where('name=?', (conf["name"],)).select() |
| if now_db_info: |
| public.M('databases').where('name=?', (conf["name"],)).delete() |
| db_info = bakup_config['mysql_info'] |
| db_info.pop('id') |
| public.M('databases').insert(db_info) |
| self.print_log('mysql{}远程数据库配置恢复完成'.format(conf["name"])) |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", 1, conf["name"], msg="还原mysql{}数据库成功".format(conf["name"])) |
| return |
|
|
| |
| self.print_log('开始恢复mysql{}数据库配置'.format(conf["name"])) |
| now_db_info = public.M('databases').where('name=?', (conf["name"],)).select() |
| if now_db_info and not isinstance(now_db_info, str): |
| now_db_info = now_db_info[0] |
| now_db_info['conn_config'] = bakup_config['mysql_info']['conn_config'] |
| now_db_info['sid'] = bakup_config['mysql_info']['sid'] |
| public.M('databases').where('name=?', (conf["name"],)).update(now_db_info) |
| else: |
| |
| args = public.dict_obj() |
| args.name = bakup_config['mysql_info']['name'] |
| args.db_user = bakup_config['mysql_info']['username'] |
| args.password = bakup_config['mysql_info']['password'] |
| args.dataAccess = "127.0.0.1" |
| args.address = "127.0.0.1" |
| args.codeing = 'utf8mb4' |
| args.dtype = 'MYSQL' |
| args.ps = bakup_config['mysql_info']['ps'] |
| args.sid = bakup_config['mysql_info']['sid'] |
| args.list_ip = '0.0.0.0/0' |
| args.host = '' |
| res = database.database().AddDatabase(args) |
| if not res['status']: |
| self.print_log("创建mysql{}数据库失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", 2, conf["name"], msg="创建mysql{}数据库失败,{}".format(conf["name"], res['msg'])) |
| return |
| self.print_log('mysql{}数据库配置恢复完成'.format(conf["name"])) |
|
|
| |
| self.print_log('开始还原mysql{}数据库权限'.format(conf["name"])) |
| access = bakup_config["sql_power"] |
| args = public.dict_obj() |
| args.name = conf["name"] |
| args.dataAccess = access |
| args.address = '' |
| args.access = access |
| res = database.database().SetDatabaseAccess(args) |
| |
| if not res['status']: |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", 2, conf["name"], msg="还原mysql{}数据库权限失败".format(conf["name"])) |
| self.print_log("还原mysql{}数据库权限失败".format(conf["name"])) |
| return |
| self.print_log('mysql{}数据库权限恢复完成'.format(conf["name"])) |
|
|
| |
| self.print_log('开始还原mysql{}数据库数据'.format(conf["name"])) |
|
|
| res = self.uncopy_file(bakup_config["sql_data"], '/tmp/{}.sql'.format(conf["name"]), isfile=True, unbak=True) |
| if not res: |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", 2, conf["name"], msg="还原mysql{}数据库数据解压失败".format(conf["name"])) |
| self.print_log("还原mysql{}数据库数据解压失败".format(conf["name"])) |
| _MYSQL_BIN = public.get_mysql_bin() |
| db_charset = public.get_database_character(conf['name']) |
| db_password = public.M("config").where("id=?", (1,)).getField("mysql_root") |
| if not db_password: |
| return public.returnMsg(False, "数据库密码为空!请先设置数据库密码!") |
| try: |
| db_port = int(panelMysql.panelMysql().query("show global variables like 'port'")[0][1]) |
| except: |
| db_port = 3306 |
| db_host = "localhost" |
| db_user = "root" |
| shell = "'{mysql_bin}' --force --default-character-set='{db_charset}' --host='{db_host}' --port={db_port} --user='{db_user}' --password='{password}' '{db_name}'".format( |
| mysql_bin=_MYSQL_BIN, |
| db_charset=db_charset, |
| db_host=db_host, |
| db_port=db_port, |
| db_user=db_user, |
| password=db_password, |
| db_name=conf["name"], |
| ) |
| public.ExecShell("{} < {} &>> {}".format(shell, '/tmp/{}.sql'.format(conf["name"]), self.logs_file)) |
| |
| now_sql_info = database.database().GetInfo(public.to_dict_obj({'db_name': conf["name"]})) |
| if now_sql_info['data_size'] != bakup_config["sql_info"]['data_size']: |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", 2, conf["name"], msg="还原mysql{}数据库数据失败".format(conf["name"])) |
| self.print_log("还原mysql{}数据库数据失败".format(conf["name"])) |
| return |
| self.print_log('mysql{}数据库数据大小校验完成{}'.format(conf["name"], now_sql_info['data_size'])) |
| self.print_log('mysql{}数据库数据恢复完成'.format(conf["name"])) |
|
|
| self.print_log("->>>还原mysql数据库:{}完成".format(conf["name"])) |
| self.change_reduction_status("data_list", "sql_list", "mysql", "reduction_status", 1, conf["name"], msg="还原mysql{}数据库成功".format(conf["name"])) |
|
|
| def reduction_mongodb_data(self, conf): |
| self.print_log("->>>开始还原mongodb数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原mongodb数据:{}完成".format(conf["name"])) |
|
|
| def reduction_redis_data(self, conf): |
| self.print_log("->>>开始还原redis数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原redis数据:{}完成".format(conf["name"])) |
|
|
| def reduction_pgsql_data(self, conf): |
| self.print_log("->>>开始还原pgsql数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原pgsql数据:{}完成".format(conf["name"])) |
|
|
| def reduction_ftp_data(self, conf): |
| self.print_log("->>>开始还原ftp数据:{}".format(conf["name"])) |
| self.change_reduction_status("data_list", "ftp_list", conf["name"], "reduction_status", -1, msg="开始还原ftp{}数据".format(conf["name"])) |
| ftp_info = self.backup_task_data['data_list']['ftp_list'].get(conf['name'], {}) |
| if not ftp_info: |
| self.print_log("获取ftp{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "ftp_list", conf["name"], "reduction_status", 2, msg="获取ftp{}备份信息失败".format(conf["name"])) |
| return |
| self.print_log('开始恢复ftp{}用户'.format(conf["name"])) |
| import ftp |
| now_ftp_info = public.M('ftps').where('name=?', (conf["name"],)).select() |
| if now_ftp_info and not isinstance(now_ftp_info, str): |
| now_ftp_info = now_ftp_info[0] |
| if 'id' in ftp_info.keys(): ftp_info['ftp_info'].pop('id') |
| now_ftp_info.update(ftp_info['ftp_info']) |
| public.M('ftps').where('name=?', (conf["name"],)).update(now_ftp_info) |
| args = public.dict_obj() |
| args.id = now_ftp_info['id'] |
| args.ftp_username = ftp_info['ftp_info']["name"] |
| args.new_password = ftp_info['ftp_info']["password"] |
| args.path = ftp_info['ftp_info']["path"] |
| res = ftp.ftp().SetUser(args) |
| if not res['status']: |
| self.print_log("修改ftp{}用户失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "ftp_list", conf["name"], "reduction_status", 2, msg="修改ftp{}用户失败".format(conf["name"])) |
| return |
| self.print_log('修改ftp{}用户成功'.format(conf["name"])) |
| else: |
| args = public.dict_obj() |
| args.ftp_username = ftp_info['ftp_info']["name"] |
| args.ftp_password = ftp_info['ftp_info']["password"] |
| args.path = ftp_info['ftp_info']["path"] |
| args.ps = ftp_info['ftp_info']["ps"] |
| res = ftp.ftp().AddUser(args) |
| if not res['status']: |
| self.print_log("创建ftp{}用户失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "ftp_list", conf["name"], "reduction_status", 2, msg="创建ftp{}用户失败".format(conf["name"])) |
| return |
| self.print_log('创建ftp{}用户成功'.format(conf["name"])) |
| self.print_log('ftp{}用户恢复完成'.format(conf["name"])) |
| |
| self.print_log('开始还原ftp{}数据'.format(conf["name"])) |
| res = self.uncopy_file(ftp_info["ftp_data"], ftp_info['ftp_info']["path"], isfile=False, unbak=True) |
| if not res: |
| self.change_reduction_status("data_list", "ftp_list", conf["name"], "reduction_status", 2, msg="还原ftp{}数据失败".format(conf["name"])) |
| self.print_log("还原ftp{}数据失败".format(conf["name"])) |
| self.print_log('ftp{}数据恢复完成'.format(conf["name"])) |
| self.print_log("->>>还原ftp:{}完成".format(conf["name"])) |
| self.change_reduction_status("data_list", "ftp_list", conf["name"], "reduction_status", 1, msg="还原ftp{}成功".format(conf["name"])) |
|
|
| def reduction_terminal_data(self, conf): |
| self.print_log("->>>开始还原terminal数据") |
| self.print_log(conf) |
| backup_conf = self.backup_task_data['data_list']['terminal_list'][conf['name']] |
| terminal = "/www/server/panel/config/ssh_info" |
| self.print_log('开始还原terminal数据') |
| res = self.uncopy_file(backup_conf["terminal_data"], terminal, isfile=False) |
| if not res: |
| self.change_reduction_status("data_list", "terminal_list", conf["name"], "reduction_status", 2, msg="还原{}数据失败".format(conf["name"])) |
| self.print_log("还原terminal数据失败") |
| public.ExecShell('rm -rf {}'.format(terminal)) |
| public.ExecShell('mv {}_bak {} -f'.format(terminal, terminal)) |
| return |
| self.print_log("->>>还原terminal数据完成") |
| self.change_reduction_status("data_list", "terminal_list", conf["name"], "reduction_status", 1, msg="还原{}数据成功".format(conf["name"])) |
|
|
| def reduction_crontab_data(self, conf): |
| self.print_log("->>>开始还原crontab数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.change_reduction_status("data_list", "crontab_list", conf["name"], "reduction_status", -1, msg="开始还原计划任务{}数据".format(conf["name"])) |
| backup_conf = self.backup_task_data['data_list']['crontab_list'] |
| cron_list = public.M('crontab').select() |
| cron_list = [i['name'] for i in cron_list] |
| |
| successful_imports = 0 |
| failed_tasks = [] |
| import crontab |
| for task in backup_conf['crontab']: |
| if task['name'] not in cron_list: |
| |
| new_task = { |
| "name": task['name'], |
| "type": task['type'], |
| "where1": task['where1'], |
| "hour": task['where_hour'], |
| "minute": task['where_minute'], |
| "status": task['status'], |
| "save": task['save'], |
| "backupTo": task['backupTo'], |
| "sType": task['sType'], |
| "sBody": task['sBody'], |
| "sName": task['sName'], |
| "urladdress": task['urladdress'], |
| "save_local": task['save_local'], |
| "notice": task['notice'], |
| "notice_channel": task['notice_channel'], |
| "db_type": task['db_type'], |
| "split_type": task['split_type'], |
| "split_value": task['split_value'], |
| "keyword": task['keyword'], |
| "post_param": task['post_param'], |
| "flock": task['flock'], |
| "time_set": task['time_set'], |
| "backup_mode": task['backup_mode'], |
| "db_backup_path": task['db_backup_path'], |
| "time_type": task['time_type'], |
| "special_time": task['special_time'], |
| "user_agent": task['user_agent'], |
| "version": task['version'], |
| "table_list": task['table_list'], |
| "result": task['result'], |
| "log_cut_path": task['log_cut_path'], |
| "rname": task['rname'], |
| "type_id": task['type_id'], |
| "second": task.get('second', ''), |
| } |
|
|
| result = crontab.crontab().AddCrontab(new_task) |
| if result.get('status', False): |
| successful_imports += 1 |
| else: |
| failed_tasks.append(task['name']) |
| else: |
| self.print_log("计划任务{}已存在".format(task['name'])) |
|
|
| if failed_tasks: |
| self.print_log("以下任务导入失败:{}".format(failed_tasks)) |
| self.change_reduction_status("data_list", "crontab_list", conf["name"], "reduction_status", 2, msg="以下任务导入失败:{}".format(failed_tasks)) |
| self.print_log("->>>还原计划任务数据:{}完成".format(conf["name"])) |
| self.change_reduction_status("data_list", "crontab_list", conf["name"], "reduction_status", 1, msg="还原计划任务{}成功".format(conf["name"])) |
|
|
| def reduction_port_data(self, conf): |
| self.print_log("->>>开始还原端口数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.change_reduction_status("data_list", "safety", "port_list", "reduction_status", -1, conf["name"], msg="开始还原端口{}数据".format(conf["name"])) |
| |
| backup_conf = self.backup_task_data['data_list']['safety']['port_list']['端口规则'] |
| self.print_log(backup_conf) |
| self.print_log('开始解压端口数据') |
| res = self.uncopy_file(backup_conf["port_data"], backup_conf['port_data_path'], md5=backup_conf['port_data_md5']) |
| if not res: |
| self.change_reduction_status("data_list", "safety", "port_list", "reduction_status", 2, conf["name"], msg="解压端口数据失败") |
| self.print_log("解压端口数据失败") |
| return |
| res = firewall_main().import_rules(public.to_dict_obj({"rule": "port", "file": backup_conf['port_data_path']})) |
| if not res['status']: |
| self.change_reduction_status("data_list", "safety", "port_list", "reduction_status", 2, conf["name"], msg="还原端口数据失败" + res['msg']) |
| self.print_log("还原端口数据失败" + res['msg']) |
| return |
| self.print_log("->>>还原端口数据:{}完成".format(conf["name"])) |
| self.change_reduction_status("data_list", "safety", "port_list", "reduction_status", 1, conf["name"], msg="还原端口数据成功") |
|
|
| def reduction_port_redirect_data(self, conf): |
| self.print_log("->>>开始还原端口转发数据:{}".format(conf["name"])) |
| self.change_reduction_status("data_list", "safety", "port_redirect", "reduction_status", -1, conf["name"], msg="开始还原端口转发{}数据".format(conf["name"])) |
| self.print_log(conf) |
| backup_conf = self.backup_task_data['data_list']['safety']['port_redirect']['端口转发'] |
| if not backup_conf: |
| self.print_log("获取port_redirect{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "safety", "port_redirect", "reduction_status", 2, conf["name"], msg="获取端口转发{}备份信息失败".format(conf["name"])) |
| return |
| self.print_log('开始解压port_redirect数据') |
| res = self.uncopy_file(backup_conf["forward"], backup_conf['forward_path'], md5=backup_conf['forward_md5']) |
| if not res: |
| self.change_reduction_status("data_list", "safety", "port_redirect", "reduction_status", 2, conf["name"], msg="解压端口转发数据失败") |
| self.print_log("解压端口转发数据失败") |
| return |
|
|
| res = firewall_main().import_rules(public.to_dict_obj({"rule": "port_redirect", "file": backup_conf['forward_path']})) |
| if not res['status']: |
| self.change_reduction_status("data_list", "safety", "port_redirect", "reduction_status", 2, conf["name"], msg="还原端口转发数据失败" + res['msg']) |
| self.print_log("还原port_redirect数据失败" + res['msg']) |
| return |
| self.change_reduction_status("data_list", "safety", "port_redirect", "reduction_status", 1, conf["name"], msg="还原端口转发数据成功") |
| self.print_log("->>>还原端口转发数据:{}完成".format(conf["name"])) |
|
|
| def reduction_area_data(self, conf): |
| self.print_log("->>>开始还原地区限制数据:{}".format(conf["name"])) |
| self.change_reduction_status("data_list", "safety", "area_list", "reduction_status", -1, conf["name"], msg="开始还原地区限制{}数据".format(conf["name"])) |
| backup_conf = self.backup_task_data['data_list']['safety']['area_list'][conf['name']] |
| area_data_path = "/www/server/panel/data/firewall/country.json" |
| if not backup_conf: |
| self.print_log("获取地区限制{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "safety", "area_list", "reduction_status", 2, conf["name"], msg="获取area{}备份信息失败".format(conf["name"])) |
| return |
| |
| self.print_log('开始解压地区限制数据') |
| res = self.uncopy_file(backup_conf["area_data"], area_data_path, md5=backup_conf['area_data_md5']) |
| if not res: |
| self.change_reduction_status("data_list", "safety", "area_list", "reduction_status", 2, conf["name"], msg="解压地区限制数据失败") |
| self.print_log("解压地区限制数据失败") |
| return |
|
|
| res = safe_firewall_main().import_rules(public.to_dict_obj({"rule_name": "country_rule", "file_name": "country.json"})) |
| if not res['status']: |
| self.change_reduction_status("data_list", "safety", "area_list", "reduction_status", 2, conf["name"], msg="还原地区限制数据失败" + res['msg']) |
| self.print_log("还原area数据失败" + res['msg']) |
| return |
|
|
| self.change_reduction_status("data_list", "safety", "area_list", "reduction_status", 1, conf["name"], msg="还原地区限制数据成功") |
| self.print_log("->>>还原地区限制数据:{}完成".format(conf["name"])) |
|
|
| def reduction_ip_data(self, conf): |
| self.print_log("->>>开始还原ip数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.change_reduction_status("data_list", "safety", "ip_list", "reduction_status", -1, conf["name"], msg="开始还原ip{}数据".format(conf["name"])) |
| backup_conf = self.backup_task_data['data_list']['safety']['ip_list'][conf['name']] |
| if not backup_conf: |
| self.print_log("获取ip{}备份信息失败".format(conf["name"])) |
| self.change_reduction_status("data_list", "safety", "ip_list", "reduction_status", 2, conf["name"], msg="获取ip{}备份信息失败".format(conf["name"])) |
| return |
|
|
| |
| self.print_log('开始解压ip数据') |
| res = self.uncopy_file(backup_conf["ip_data"], backup_conf['ip_list_path'], md5=backup_conf['ip_data_md5']) |
| if not res: |
| self.change_reduction_status("data_list", "safety", "ip_list", "reduction_status", 2, conf["name"], msg="解压ip数据失败") |
| self.print_log("解压ip数据失败") |
| return |
|
|
| res = firewall_main().import_rules(public.to_dict_obj({"rule": "ip", "file": backup_conf['ip_list_path']})) |
| if not res['status']: |
| self.change_reduction_status("data_list", "safety", "ip_list", "reduction_status", 2, conf["name"], msg="还原ip数据失败" + res['msg']) |
| self.print_log("还原ip数据失败" + res['msg']) |
| return |
|
|
| self.change_reduction_status("data_list", "safety", "ip_list", "reduction_status", 1, conf["name"], msg="还原ip数据成功") |
| self.print_log("->>>还原ip数据:{}完成".format(conf["name"])) |
|
|
| def reduction_words_data(self, conf): |
| self.print_log("->>>开始还原words数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.change_reduction_status("data_list", "safety", "words", "reduction_status", -1, conf["name"], msg="开始还原违规关键词{}数据".format(conf["name"])) |
| backup_conf = self.backup_task_data['data_list']['safety']['words'][conf['name']] |
| self.print_log(backup_conf) |
| |
| self.print_log('开始解压words数据') |
| words_path = "/www/server/panel/config/thesaurus.json" |
| res = self.uncopy_file(backup_conf["wrods_data"], words_path, md5=backup_conf['wrod_data_md5']) |
| if not res: |
| self.change_reduction_status("data_list", "safety", "words", "reduction_status", 2, conf["name"], msg="还原违规关键词数据失败") |
| self.print_log("解压words数据失败") |
| return |
| self.change_reduction_status("data_list", "safety", "words", "reduction_status", 1, conf["name"], msg="还原违规关键词数据") |
| self.print_log("->>>还原违规关键词数据:{}完成".format(conf["name"])) |
|
|
| def reduction_sqlite_data(self, conf): |
| self.print_log("->>>开始还原sqlite数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.print_log("->>>还原sqlite数据:{}完成".format(conf["name"])) |
|
|
| def reduction_ssh_config_data(self, conf): |
| self.print_log("->>>开始还原ssh数据:{}".format(conf["name"])) |
| self.print_log(conf) |
| self.change_reduction_status("data_list", "safety", "ssh_config", "reduction_status", -1, conf["name"], msg="开始还原ssh{}数据".format(conf["name"])) |
| backup_conf = self.backup_task_data['data_list']['safety']['ssh_config'][conf['name']] |
| self.print_log(backup_conf) |
| ssh_config_path = '/etc/ssh/sshd_config' |
| self.print_log('开始解压ssh数据') |
| res = self.uncopy_file(backup_conf["ssh_data"], ssh_config_path, md5=backup_conf['ssh_data_md5']) |
| if not res: |
| self.change_reduction_status("data_list", "safety", "ssh_config", "reduction_status", 2, conf["name"], msg="还原ssh数据失败") |
| self.print_log("还原ssh_config数据失败") |
| return |
|
|
| public.ExecShell('systemctl restart sshd') |
| self.print_log("->>>还原ssfig数据:{}完成".format(conf["name"])) |
| self.change_reduction_status("data_list", "safety", "ssh_config", "reduction_status", 1, conf["name"], msg="还原ssh数据成功") |
|
|
| def create_queue(self, get): |
| """ |
| 创建任务队列(用于执行备份或还原任务) |
| |
| :param get: 包含任务 ID 和任务类型的对象 |
| - id (str): 任务的唯一标识符 |
| - type (str): 任务类型,1 表示备份,2 表示还原 |
| """ |
| |
| id = get.id |
| type = get.type |
| print(type) |
| |
| name = '备份任务' if type == 1 else '还原任务' |
| print(name) |
| |
| import panelTask |
| print("btpython /www/server/panel/class/panelModel/whole_machine_backupModel.py {} {} &> {}".format(id, type, self.logs_file )) |
| |
| panelTask.bt_task().create_task( |
| name, |
| 0, |
| "btpython /www/server/panel/class/panelModel/whole_machine_backupModel.py {} {} &> {}".format( |
| id, |
| type, |
| self.logs_file |
| ) |
| ) |
|
|
| |
| self.print_log("创建{}成功".format(name)) |
|
|
|
|
| def input(self, get): |
| |
| original_file_name = get.f_name |
| clean_file_name = original_file_name |
| if '(' in original_file_name and ')' in original_file_name: |
| clean_file_name = original_file_name.split('(')[0].strip() + ".tar.gz" |
|
|
| |
| file_name = self.backup_path + clean_file_name |
| if not os.path.exists(self.backup_path): |
| os.makedirs(self.backup_path) |
| if clean_file_name in self.config: |
| return public.returnMsg(False, '已存在相同的任务,请先删除后再导入!') |
| from files import files |
| fileObj = files() |
| get.f_path = self.backup_path |
| ff = fileObj.upload(get) |
| if isinstance(ff, int): |
| return ff |
| if not ff['status']: |
| return ff |
| |
| print(public.ExecShell('cd {} && tar -zxvf {} ./{} '.format(self.backup_path, clean_file_name, clean_file_name.rstrip('.tar.gz')))) |
| print(clean_file_name) |
| all_config_path = os.path.join(self.backup_path, clean_file_name.rstrip('.tar.gz')) |
| print(all_config_path) |
| time.sleep(0.2) |
| if not os.path.exists(all_config_path): |
| return public.returnMsg(False, '未找到配置文件!') |
| try: |
| res=json.loads(public.readFile(all_config_path)) |
| res[clean_file_name.rstrip('.tar.gz')]['status'] = 1 |
| self.config.update(res) |
| except Exception as e: |
| print(e) |
| return public.returnMsg(False, '配置文件解析失败!') |
| public.ExecShell('rm -rf {}'.format(all_config_path)) |
|
|
| |
| if os.path.exists('{}backup.json'.format(self.backup_path)): |
| public.ExecShell('rm -rf {}backup.json'.format(self.backup_path)) |
| public.ExecShell('cd {} && tar -zxvf {} ./backup.json'.format(self.backup_path, file_name)) |
| time.sleep(0.1) |
| public.ExecShell('mv {}backup.json {}_backup.json'.format(self.backup_path, self.backup_path+clean_file_name.rstrip('.tar.gz'))) |
| |
| if not os.path.exists(self.backup_log_path): |
| public.ExecShell('mkdir -p {}'.format(self.backup_log_path)) |
| public.ExecShell('cd {} && tar -zxvf {} ./{}_backup.log'.format(self.backup_log_path, file_name,clean_file_name.rstrip('.tar.gz'))) |
| public.writeFile(self.all_backup_config_path, json.dumps(self.config)) |
| return public.returnMsg(True, '导入成功!') |
|
|
| def cp_config(): |
| config_path = os.path.join(public.get_panel_path(), 'config/whole_machine_backup.json') |
| if not os.path.exists(config_path): |
| public.ExecShell("cp /www/backup/whole_machine_backup/whole_machine_backup.json {}".format(config_path)) |
| cp_config() |
| del cp_config |
|
|
| if __name__ == '__main__': |
| id = sys.argv[1] |
| type = sys.argv[2] |
| main = main() |
| if type == '1': |
| print('1') |
| main.backup(id) |
| elif type == '2': |
| main.reduction(id) |
| elif type == '3': |
| main.check_mysql_files(sys.argv[3], sys.argv[4]) |
| else: |
| print('参数错误!') |
| sys.exit(1) |
|
|