diff --git a/.gitignore b/.gitignore index 06328e5aa6..425a502b4d 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,7 @@ lib/python* bin pyvenv.cfg include +share pip-selfcheck.json scripts/mdserver-web @@ -141,15 +142,14 @@ data/ssl.pl data/edate.pl data/osname.pl data/system.db-journal +data/hook_*.json plugins/l2tp plugins/openlitespeed plugins/gdrive plugins/mtproxy plugins/zimg +plugins/bk_demo debug.out - - - diff --git a/README.md b/README.md index ae27463ae3..18ab35511a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -### mdserver-web 0.9.5 +### mdserver-web 0.9.6 简单的Linux面板,感谢BT.CN写出如此好的web管理软件。我一看到,就知道这是我一直想要的页面化管理方式。 复制了后台管理界面,按照自己想要的方式写了一版。 @@ -71,13 +71,11 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443: ``` -### 版本更新 0.9.5 +### 版本更新 0.9.6 -* 页面更新优化[2]. -* 修复maridb的用户管理[2]. -* Gogs初始化提示更人性. -* MySQL&&MariaDB修改密码修复. -* MySQL&&MariaDB导入修复. +* 增加插件备份功能. +* supervisor增加错误日志查看. +* MariaDB安装源优化. ### JSDelivr安装地址 @@ -127,13 +125,12 @@ curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/up ``` ### 微信赞助 -[![截图](/route/static/img/weixin_zz.jpg)](/route/static/img/weixin_zz.jpg) +[![截图](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/img/weixin_zz.jpg)](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/img/weixin_zz.jpg) ### 无图不真相 -[![截图](/route/static/mdw.jpg)](/route/static/mdw.jpg) - +[![截图](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/mdw.jpg)](https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/route/static/mdw.jpg) ### Stargazers over time diff --git a/class/core/crontab_api.py b/class/core/crontab_api.py index 385b04815f..a07fd0058a 100755 --- a/class/core/crontab_api.py +++ b/class/core/crontab_api.py @@ -295,9 +295,18 @@ def delLogsApi(self): # 取数据列表 def getDataListApi(self): stype = request.form.get('type', '') + + bak_data = [] + + if stype == 'sites' or stype == 'databases': + hookPath = mw.getPanelDataDir() + "/hook_backup.json" + if os.path.exists(hookPath): + t = mw.readFile(hookPath) + bak_data = json.loads(t) + if stype == 'databases': db_list = {} - db_list['orderOpt'] = [] + db_list['orderOpt'] = bak_data path = mw.getServerDir() + '/mysql' if not os.path.exists(path + '/mysql.db'): db_list['data'] = [] @@ -307,8 +316,9 @@ def getDataListApi(self): return mw.getJson(db_list) data = {} + data['orderOpt'] = bak_data + data['data'] = mw.M(stype).field('name,ps').select() - data['orderOpt'] = [] return mw.getJson(data) ##### ----- start ----- ### @@ -411,16 +421,13 @@ def getShell(self, param): 'rememory': head + "/bin/bash " + script_dir + '/rememory.sh' } if param['backup_to'] != 'localhost': - cfile = mw.getServerDir() + "/mdserver-web/plugin/" + \ - param['backup_to'] + "/" + param['backup_to'] + "_main.py" - if not os.path.exists(cfile): - cfile = script_dir + "/backup_" + \ - param['backup_to'] + ".py" + cfile = mw.getPluginDir() + "/" + \ + param['backup_to'] + "/index.py" wheres = { - 'path': head + "python " + cfile + " path " + param['sname'] + " " + str(param['save']), - 'site': head + "python " + cfile + " site " + param['sname'] + " " + str(param['save']), - 'database': head + "python " + cfile + " database " + param['sname'] + " " + str(param['save']), - 'logs': head + "python " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']), + 'path': head + "python3 " + cfile + " path " + param['sname'] + " " + str(param['save']), + 'site': head + "python3 " + cfile + " site " + param['sname'] + " " + str(param['save']), + 'database': head + "python3 " + cfile + " database " + param['sname'] + " " + str(param['save']), + 'logs': head + "python3 " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']), 'rememory': head + "/bin/bash " + script_dir + '/rememory.sh' } try: diff --git a/class/core/files_api.py b/class/core/files_api.py index a19f8e4605..bc97a1482a 100755 --- a/class/core/files_api.py +++ b/class/core/files_api.py @@ -676,8 +676,7 @@ def getBody(self, path): data['encoding'] = 'utf-8' if char['encoding'] == 'Big5': data['encoding'] = 'BIG5' - if not char['encoding'] in ['GBK', 'utf-8', - 'BIG5']: + if not char['encoding'] in ['GBK', 'utf-8', 'BIG5']: data['encoding'] = 'utf-8' try: if sys.version_info[0] == 2: diff --git a/class/core/mw.py b/class/core/mw.py index 70141afeae..607354cfc2 100755 --- a/class/core/mw.py +++ b/class/core/mw.py @@ -57,10 +57,22 @@ def getPluginDir(): return getRunDir() + '/plugins' +def getPanelDataDir(): + return getRunDir() + '/data' + + def getServerDir(): return getRootDir() + '/server' +def getLogsDir(): + return getRootDir() + '/wwwlogs' + + +def getBackupDir(): + return getRootDir() + '/backup' + + def getWwwDir(): file = getRunDir() + '/data/site.pl' if os.path.exists(file): @@ -73,14 +85,6 @@ def setWwwDir(wdir): return writeFile(file, wdir) -def getLogsDir(): - return getRootDir() + '/wwwlogs' - - -def getBackupDir(): - return getRootDir() + '/backup' - - def setBackupDir(bdir): file = getRunDir() + '/data/backup.pl' return writeFile(file, bdir) diff --git a/class/core/plugins_api.py b/class/core/plugins_api.py index f144fdfc98..5a720b9cc9 100755 --- a/class/core/plugins_api.py +++ b/class/core/plugins_api.py @@ -114,6 +114,7 @@ def installApi(self): return mw.returnJson(False, '配置文件不存在!', ()) pluginInfo = json.loads(mw.readFile(infoJsonPos)) + self.hookInstall(pluginInfo) execstr = "cd " + os.getcwd() + "/plugins/" + \ name + " && /bin/bash " + pluginInfo["shell"] \ @@ -131,6 +132,55 @@ def installApi(self): mw.triggerTask() return mw.returnJson(True, '已将安装任务添加到队列!') + def hookInstallFile(self, hook_name, info): + hookPath = mw.getPanelDataDir() + "/hook_" + hook_name + ".json" + data = [] + if os.path.exists(hookPath): + t = mw.readFile(hookPath) + data = json.loads(t) + + isNeedAdd = True + for x in range(len(data)): + if data[x]['title'] == info['title'] and data[x]['name'] == info['name']: + isNeedAdd = False + + if isNeedAdd: + tmp = {} + tmp['title'] = info['title'] + tmp['name'] = info['name'] + data.append(tmp) + mw.writeFile(hookPath, json.dumps(data)) + + def hookUninstallFile(self, hook_name, info): + hookPath = mw.getPanelDataDir() + "/hook_" + hook_name + ".json" + data = [] + if os.path.exists(hookPath): + t = mw.readFile(hookPath) + data = json.loads(t) + + for idx in range(len(data)): + if data[idx]['title'] == info['title'] and data[idx]['name'] == info['name']: + data.remove(data[idx]) + mw.writeFile(hookPath, json.dumps(data)) + + def hookInstall(self, info): + if 'hook' in info: + hooks = info['hook'] + for x in hooks: + if x in ['backup']: + self.hookInstallFile(x, info) + return True + return False + + def hookUninstall(self, info): + if 'hook' in info: + hooks = info['hook'] + for x in hooks: + if x in ['backup']: + self.hookUninstallFile(x, info) + return True + return False + def uninstallOldApi(self): rundir = mw.getRunDir() name = request.form.get('name', '') @@ -147,7 +197,6 @@ def uninstallOldApi(self): return mw.returnJson(False, "配置文件不存在!", ()) pluginInfo = json.loads(mw.readFile(infoJsonPos)) - execstr = "cd " + os.getcwd() + "/plugins/" + \ name + " && /bin/bash " + pluginInfo["shell"] \ + " uninstall " + version @@ -175,13 +224,13 @@ def uninstallApi(self): return mw.returnJson(False, "配置文件不存在!", ()) pluginInfo = json.loads(mw.readFile(infoJsonPos)) - + self.hookUninstall(pluginInfo) execstr = "cd " + os.getcwd() + "/plugins/" + \ name + " && /bin/bash " + pluginInfo["shell"] \ + " uninstall " + version data = mw.execShell(execstr) - if mw.isAppleSystem(): + if mw.isDebugMode(): print(execstr) print(data[0], data[1]) self.removeIndex(name, version) @@ -793,7 +842,7 @@ def getIndexList(self): print('getIndexList:', e) # 使用gevent模式时,无法使用多进程 - #plist = self.checkStatusMProcess(plist) + # plist = self.checkStatusMProcess(plist) plist = self.checkStatusMThreads(plist) return plist diff --git a/plugins/mariadb/versions/10.6/install.sh b/plugins/mariadb/versions/10.6/install.sh index ae3506bc75..7fbb64cc77 100755 --- a/plugins/mariadb/versions/10.6/install.sh +++ b/plugins/mariadb/versions/10.6/install.sh @@ -14,7 +14,7 @@ sysName=`uname` install_tmp=${rootPath}/tmp/mw_install.pl mariadbDir=${serverPath}/source/mariadb -MY_VER=10.6.8 +MY_VER=10.6.9 Install_app() { @@ -57,10 +57,15 @@ Install_app() fi # ----- cpu end ------ + # https://mirrors.aliyun.com/mariadb/mariadb-10.8.3/source/mariadb-10.8.3.tar.gz if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then - # https://mirrors.aliyun.com/mariadb/mariadb-10.8.3/source/mariadb-10.8.3.tar.gz - wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz - # wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz + wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz + + fi + + # https://downloads.mariadb.org/interstitial/mariadb-10.6.8/source/mariadb-10.6.8.tar.gz + if [ "$?" != "0" ];then + wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz fi if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then diff --git a/plugins/mariadb/versions/10.7/install.sh b/plugins/mariadb/versions/10.7/install.sh index ab3508dabc..d1d38b238f 100755 --- a/plugins/mariadb/versions/10.7/install.sh +++ b/plugins/mariadb/versions/10.7/install.sh @@ -14,7 +14,7 @@ sysName=`uname` install_tmp=${rootPath}/tmp/mw_install.pl mariadbDir=${serverPath}/source/mariadb -MY_VER=10.7.4 +MY_VER=10.7.5 Install_app() { @@ -58,14 +58,16 @@ Install_app() # ----- cpu end ------ if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then - wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz - # wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz + wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz + fi + + if [ "$?" != "0" ];then + wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz fi if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz fi - if [ ! -d $serverPath/mariadb ];then cd ${mariadbDir}/mariadb-${MY_VER} && cmake \ diff --git a/plugins/mariadb/versions/10.8/install.sh b/plugins/mariadb/versions/10.8/install.sh index 32b4418035..b2bda21275 100755 --- a/plugins/mariadb/versions/10.8/install.sh +++ b/plugins/mariadb/versions/10.8/install.sh @@ -14,7 +14,7 @@ sysName=`uname` install_tmp=${rootPath}/tmp/mw_install.pl mariadbDir=${serverPath}/source/mariadb -MY_VER=10.8.3 +MY_VER=10.8.4 Install_app() { @@ -58,8 +58,11 @@ Install_app() # ----- cpu end ------ if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then - wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz - # wget -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz + wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz + fi + + if [ "$?" != "0" ];then + wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://downloads.mariadb.org/interstitial/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz fi if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then diff --git a/plugins/mysql/index.html b/plugins/mysql/index.html index ee348dbdc2..8525ae05ec 100755 --- a/plugins/mysql/index.html +++ b/plugins/mysql/index.html @@ -53,7 +53,7 @@ .conf_p span { display: inline-block; margin-right: 10px; - width: 95px; + width: 135px; text-align: right; } diff --git a/plugins/php/versions/74/install.sh b/plugins/php/versions/74/install.sh index 9e93d2370d..18a555a412 100755 --- a/plugins/php/versions/74/install.sh +++ b/plugins/php/versions/74/install.sh @@ -39,7 +39,11 @@ if [ ! -d $sourcePath/php/php${PHP_VER} ];then mv $sourcePath/php/php-${version} $sourcePath/php/php${PHP_VER} fi - +if [ ! -d $sourcePath/php/php${PHP_VER} ];then + rm -rf $sourcePath/php/php-${version}.tar.xz + echo "reinstall php${version}" + exit 1 +fi cd $sourcePath/php/php${PHP_VER} diff --git a/plugins/rsyncd/js/rsyncd.js b/plugins/rsyncd/js/rsyncd.js index e70a76e543..d991200934 100755 --- a/plugins/rsyncd/js/rsyncd.js +++ b/plugins/rsyncd/js/rsyncd.js @@ -339,7 +339,10 @@ function createSendTask(name = ''){ layer.msg(rdata.msg,{icon:rdata.status?1:2,time:2000,shade: [0.3, '#000']}); if (rdata.status){ - setTimeout(function(){layer.close(index);},2000); + setTimeout(function(){ + layer.close(index); + lsyncdSend(); + },2000); return; } }); diff --git a/plugins/supervisor/index.py b/plugins/supervisor/index.py index 8acfca0b77..1d7c067583 100755 --- a/plugins/supervisor/index.py +++ b/plugins/supervisor/index.py @@ -477,6 +477,28 @@ def readConfigLogTpl(): return mw.returnJson(False, 'OK', '') +def readConfigLogErrorTpl(): + args = getArgs() + data = checkArgs(args, ['file']) + if not data[0]: + return data[1] + file_log = args['file'] + line_log = args['line'] + + with open(file_log, "r") as fr: + infos = fr.readlines() + + stderr_logfile = '' + for line in infos: + if "stderr_logfile=" in line.strip(): + stderr_logfile = line.strip().split('=')[1] + + if stderr_logfile != '': + data = mw.getNumLines(stderr_logfile, int(line_log)) + return mw.returnJson(True, 'OK', data) + return mw.returnJson(False, 'OK', '') + + def supClearLog(): args = getArgs() data = checkArgs(args, ['file']) @@ -529,6 +551,8 @@ def runLog(): print(readConfigTpl()) elif func == 'read_config_log_tpl': print(readConfigLogTpl()) + elif func == 'read_config_log_error_tpl': + print(readConfigLogErrorTpl()) elif func == 'sup_clear_log': print(supClearLog()) elif func == 'conf': diff --git a/plugins/supervisor/js/supervisor.js b/plugins/supervisor/js/supervisor.js index 32cb5265d5..844e9fb2a6 100755 --- a/plugins/supervisor/js/supervisor.js +++ b/plugins/supervisor/js/supervisor.js @@ -405,7 +405,7 @@ function supConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_fun return; } - $("#textBody").empty().text(rdata.data); + $("#textBody").empty().html(rdata.data); $(".CodeMirror").remove(); var editor = CodeMirror.fromTextArea(document.getElementById("textBody"), { extraKeys: { @@ -424,7 +424,7 @@ function supConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_fun $(".CodeMirror-scroll").css({"height":"300px","margin":0,"padding":0}); $("#onlineEditFileBtn").unbind('click'); $("#onlineEditFileBtn").click(function(){ - $("#textBody").text(editor.getValue()); + $("#textBody").html(editor.getValue()); pluginConfigSave(fileName); }); },'json'); @@ -474,6 +474,7 @@ function supLogs(_name, config_tpl_func, read_config_tpl_func,line){ var con = '