diff --git a/panel_task.py b/panel_task.py index 84d39bd4f..263e9366f 100755 --- a/panel_task.py +++ b/panel_task.py @@ -117,7 +117,7 @@ def mw_async(f): @mw_async def restartMw(): time.sleep(1) - cmd = mw.getRunDir() + '/scripts/init.d/mw reload &' + cmd = mw.getPanelDir() + '/scripts/init.d/mw reload &' mw.execShell(cmd) @@ -225,173 +225,15 @@ def siteEdate(): def systemTask(): + from utils.system import monitor # 系统监控任务 try: - import system_api - import psutil - sm = system_api.system_api() - filename = 'data/control.conf' - - sql = db.Sql().dbfile('system') - csql = mw.readFile('data/sql/system.sql') - csql_list = csql.split(';') - for index in range(len(csql_list)): - sql.execute(csql_list[index], ()) - - cpuIo = cpu = {} - cpuCount = psutil.cpu_count() - used = count = 0 - reloadNum = 0 - network_up = network_down = diskio_1 = diskio_2 = networkInfo = cpuInfo = diskInfo = None - while True: - if not os.path.exists(filename): - time.sleep(10) - continue - - day = 30 - try: - day = int(mw.readFile(filename)) - if day < 1: - time.sleep(10) - continue - except: - day = 30 - - tmp = {} - # 取当前CPU Io - tmp['used'] = psutil.cpu_percent(interval=1) - if tmp['used'] > 80: - panel_title = mw.getConfig('title') - ip = mw.getHostAddr() - now_time = mw.getDateFromNow() - msg = now_time + '|节点[' + panel_title + ':' + ip + \ - ']处于高负载[' + str(tmp['used']) + '],请排查原因!' - mw.notifyMessage(msg, '面板监控', 600) - - if not cpuInfo: - tmp['mem'] = sm.getMemUsed() - cpuInfo = tmp - - if cpuInfo['used'] < tmp['used']: - tmp['mem'] = sm.getMemUsed() - cpuInfo = tmp - - # 取当前网络Io - networkIo = sm.psutilNetIoCounters() - if not network_up: - network_up = networkIo[0] - network_down = networkIo[1] - tmp = {} - tmp['upTotal'] = networkIo[0] - tmp['downTotal'] = networkIo[1] - tmp['up'] = round(float((networkIo[0] - network_up) / 1024), 2) - tmp['down'] = round(float((networkIo[1] - network_down) / 1024), 2) - tmp['downPackets'] = networkIo[3] - tmp['upPackets'] = networkIo[2] - - network_up = networkIo[0] - network_down = networkIo[1] - - if not networkInfo: - networkInfo = tmp - if (tmp['up'] + tmp['down']) > (networkInfo['up'] + networkInfo['down']): - networkInfo = tmp - # 取磁盘Io - # if os.path.exists('/proc/diskstats'): - diskio_2 = psutil.disk_io_counters() - if not diskio_1: - diskio_1 = diskio_2 - tmp = {} - tmp['read_count'] = diskio_2.read_count - diskio_1.read_count - tmp['write_count'] = diskio_2.write_count - diskio_1.write_count - tmp['read_bytes'] = diskio_2.read_bytes - diskio_1.read_bytes - tmp['write_bytes'] = diskio_2.write_bytes - diskio_1.write_bytes - tmp['read_time'] = diskio_2.read_time - diskio_1.read_time - tmp['write_time'] = diskio_2.write_time - diskio_1.write_time - - if not diskInfo: - diskInfo = tmp - else: - diskInfo['read_count'] += tmp['read_count'] - diskInfo['write_count'] += tmp['write_count'] - diskInfo['read_bytes'] += tmp['read_bytes'] - diskInfo['write_bytes'] += tmp['write_bytes'] - diskInfo['read_time'] += tmp['read_time'] - diskInfo['write_time'] += tmp['write_time'] - diskio_1 = diskio_2 - - # print diskInfo - if count >= 12: - try: - addtime = int(time.time()) - deltime = addtime - (day * 86400) - - data = (cpuInfo['used'], cpuInfo['mem'], addtime) - sql.table('cpuio').add('pro,mem,addtime', data) - sql.table('cpuio').where("addtime 100: - lpro = 100 - sql.table('load_average').add('pro,one,five,fifteen,addtime', (lpro, load_average['one'], load_average['five'], load_average['fifteen'], addtime)) - - lpro = None - load_average = None - cpuInfo = None - networkInfo = None - diskInfo = None - count = 0 - reloadNum += 1 - if reloadNum > 1440: - reloadNum = 0 - mw.writeFile('logs/sys_interrupt.pl', - "reload num:" + str(reloadNum)) - restartMw() - except Exception as ex: - print(str(ex)) - mw.writeFile('logs/sys_interrupt.pl', str(ex)) - - del(tmp) - time.sleep(5) - count += 1 - except Exception as ex: - print(str(ex)) - mw.writeFile('logs/sys_interrupt.pl', str(ex)) - - restartMw() - - time.sleep(30) - systemTask() - -def systemTask2(): - # 系统监控任务 - try: - from utils.system import monitor while True: monitor.instance().run() time.sleep(5) except Exception as ex: - print(str(ex)) - mw.writeFile('logs/sys_interrupt.pl', str(ex)) - restartMw() time.sleep(30) - systemTask2() + systemTask() # -------------------------------------- PHP监控 start --------------------------------------------- # @@ -596,7 +438,7 @@ def setDaemon(t): def run(): # # 系统监控 - sysTask = threading.Thread(target=systemTask2) + sysTask = threading.Thread(target=systemTask) sysTask = setDaemon(sysTask) sysTask.start() diff --git a/panel_tools.py b/panel_tools.py index a56444a8f..89208170a 100755 --- a/panel_tools.py +++ b/panel_tools.py @@ -26,6 +26,7 @@ sys.path.append(web_dir) from admin import app from admin import model +import thisdb import core.mw as mw import core.db as db @@ -241,7 +242,7 @@ def show_panel_pwd(): print("password has been changed!") def show_panel_adminpath(): - admin_path = model.getOption('admin_path') + admin_path = thisdb.getOption('admin_path') print('/'+admin_path) @@ -289,6 +290,8 @@ def main(): set_panel_username() elif method == 'password': show_panel_pwd() + elif method == 'test': + thisdb.getOption('admin_path') elif method == 'admin_path': show_panel_adminpath() elif method == 'getServerIp': @@ -305,5 +308,4 @@ def main(): print('ERROR: Parameter error') if __name__ == "__main__": - with app.app_context(): - main() + main() diff --git a/web/admin/__init__.py b/web/admin/__init__.py index 87dd08ffd..55b5d89ba 100644 --- a/web/admin/__init__.py +++ b/web/admin/__init__.py @@ -93,8 +93,10 @@ with app.app_context(): if setup_db_required: setup.init_admin_user() setup.init_option() +setup.init_cmd() setup.init_db_system() + app.config['BASIC_AUTH_OPEN'] = False with app.app_context(): basic_auth = model.getOptionByJson('basic_auth', default={'open':False}) @@ -155,6 +157,7 @@ def page_unauthorized(error): # 设置模板全局变量 @app.context_processor def inject_global_variables(): + start_t = time.time() ver = config.APP_VERSION; if mw.isDebugMode(): ver = ver + str(time.time()) @@ -165,6 +168,9 @@ def inject_global_variables(): 'title' : 'MW面板', 'ip' : '127.0.0.1' } + + end_t = time.time() + print("cos:"+str(end_t-start_t)) return dict(config=g_config, data=data) diff --git a/web/admin/dashboard/__init__.py b/web/admin/dashboard/__init__.py index e3fd25933..c77e84623 100644 --- a/web/admin/dashboard/__init__.py +++ b/web/admin/dashboard/__init__.py @@ -36,6 +36,10 @@ def index(): @blueprint.route('/',endpoint='admin_safe_path',methods=['GET']) def admin_safe_path(path): db_path = model.getOption('admin_path') + + if isLogined(): + return redirect('/') + if db_path == path: return render_template('default/login.html') @@ -63,7 +67,7 @@ def webhook(): wh_install_path = mw.getServerDir() + '/webhook' if not os.path.exists(wh_install_path): - return mw.returnJson(False, '请先安装WebHook插件!') + return mw.returnData(False, '请先安装WebHook插件!') package = mw.getPanelDir() + "/plugins/webhook" if not package in sys.path: diff --git a/web/admin/model/__init__.py b/web/admin/model/__init__.py index b0821ac6d..e2bb5f82e 100644 --- a/web/admin/model/__init__.py +++ b/web/admin/model/__init__.py @@ -19,7 +19,7 @@ from .option import setOption from .sites import getSitesCount from .task import addTask -from .task import getTaskCount,getTaskUnexecutedCount,getTaskList,getTaskFirstByRun +from .task import getTaskCount,getTaskUnexecutedCount,getTaskList,getTaskFirstByRun,getTaskRunList from .task import setTaskStatus,setTaskData from .user import isLoginCheck diff --git a/web/admin/model/option.py b/web/admin/model/option.py index 98a229217..cbb277be5 100644 --- a/web/admin/model/option.py +++ b/web/admin/model/option.py @@ -71,5 +71,4 @@ def setOption(name, value, db.session.query(Option).filter_by(name=name, type=type).update({"value":value}) db.session.commit() - db.session.close() return True \ No newline at end of file diff --git a/web/admin/model/task.py b/web/admin/model/task.py index 66edfd33c..c3ba9ccc7 100644 --- a/web/admin/model/task.py +++ b/web/admin/model/task.py @@ -88,6 +88,26 @@ def getTaskList( rows.append(t) return rows +def getTaskRunList( + page: int | None = 1, + size: int | None = 10, +): + pagination = Tasks.query.filter(Tasks.status!=1).order_by(Tasks.id.asc()).paginate(page=int(page), per_page=int(size)) + + rows = [] + for item in pagination.items: + t = {} + t['id'] = item.id + t['name'] = item.name + t['type'] = item.type + t['cmd'] = item.cmd + t['start'] = item.start + t['end'] = item.end + t['status'] = item.status + t['add_time'] = item.add_time + rows.append(t) + return rows + diff --git a/web/admin/setup/__init__.py b/web/admin/setup/__init__.py index 7cd824ba3..e8ab0677a 100644 --- a/web/admin/setup/__init__.py +++ b/web/admin/setup/__init__.py @@ -11,4 +11,5 @@ from .user import init_admin_user from .option import init_option from .init_db_system import init_db_system +from .init_cmd import init_cmd diff --git a/web/admin/setup/init_cmd.py b/web/admin/setup/init_cmd.py new file mode 100644 index 000000000..434528a09 --- /dev/null +++ b/web/admin/setup/init_cmd.py @@ -0,0 +1,54 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import os +import shutil + +import core.mw as mw + +def contentReplace(src, dst): + content = mw.readFile(src) + content = content.replace("{$SERVER_PATH}", mw.getFatherDir()) + + content += "\n# make:{0}".format(mw.formatDate()) + mw.writeFile(dst, content) + + +def init_cmd(): + script = mw.getPanelDir() + '/scripts/init.d/mw.tpl' + script_bin = mw.getPanelDir() + '/scripts/init.d/mw' + contentReplace(script, script_bin) + mw.execShell('chmod +x ' + script_bin) + + # 在linux系统中,确保/etc/init.d存在 + if not mw.isAppleSystem() and not os.path.exists("/etc/rc.d/init.d"): + mw.execShell('mkdir -p /etc/rc.d/init.d') + + if not mw.isAppleSystem() and not os.path.exists("/etc/init.d"): + mw.execShell('mkdir -p /etc/init.d') + + # initd + if os.path.exists('/etc/rc.d/init.d'): + initd_bin = '/etc/rc.d/init.d/mw' + if not os.path.exists(initd_bin): + shutil.copyfile(script_bin, initd_bin) + mw.execShell('chmod +x ' + initd_bin) + # 加入自启动 + mw.execShell('which chkconfig && chkconfig --add mw') + + if os.path.exists('/etc/init.d'): + initd_bin = '/etc/init.d/mw' + if not os.path.exists(initd_bin): + import shutil + shutil.copyfile(script_bin, initd_bin) + mw.execShell('chmod +x ' + initd_bin) + # 加入自启动 + mw.execShell('which update-rc.d && update-rc.d -f mw defaults') + return True \ No newline at end of file diff --git a/web/admin/setup/option.py b/web/admin/setup/option.py index 10d739875..87f691471 100644 --- a/web/admin/setup/option.py +++ b/web/admin/setup/option.py @@ -34,9 +34,6 @@ def init_option(): # basic auth 配置 model.setOption('basic_auth', json.dumps({'open':False})) - - - # 开启后台任务 # model.setOption('run_bg_task', 'close') @@ -50,7 +47,10 @@ def init_option(): # 初始化安全路径 model.setOption('admin_path', mw.getRandomString(8)) - model.setOption('server_ip', '127.0.0.1') + + + ip = mw.getLocalIp() + model.setOption('server_ip', ip) # 默认备份目录 model.setOption('backup_path', mw.getFatherDir()+'/backup') diff --git a/web/admin/task/__init__.py b/web/admin/task/__init__.py index 2cb6ea08e..e90f33a89 100644 --- a/web/admin/task/__init__.py +++ b/web/admin/task/__init__.py @@ -17,6 +17,7 @@ from admin.model import db,Tasks from admin.user_login_check import panel_login_required import core.mw as mw +import utils.task as MwTasks blueprint = Blueprint('task', __name__, url_prefix='/task', template_folder='../../templates/default') @@ -98,9 +99,16 @@ def get_task_speed(): data['isDownload'] = False - data['task'] = model.getTaskList(status=-1) + data['task'] = model.getTaskRunList() return data - + +@blueprint.route('/remove_task', endpoint='remove_task', methods=['POST']) +@panel_login_required +def remove_task(): + task_id = request.form.get('id', '') + if task_id == '': + return mw.returnData(False, '任务ID不能为空!') + return MwTasks.removeTask(task_id) \ No newline at end of file diff --git a/web/core/mw.py b/web/core/mw.py index 840595c44..287c9bae7 100644 --- a/web/core/mw.py +++ b/web/core/mw.py @@ -199,10 +199,6 @@ def writeFile(filename, content, mode='w+'): except Exception as e: return False -def triggerTask(): - isTask = getPanelDir() + '/tmp/panelTask.pl' - writeFile(isTask, 'True') - def systemdCfgDir(): # ubuntu @@ -263,6 +259,39 @@ def getClientIp(): from flask import request return request.remote_addr.replace('::ffff:', '') +def getLocalIp(): + filename = getPanelDir()+'/data/iplist.txt' + try: + ipaddress = readFile(filename) + if not ipaddress or ipaddress == '127.0.0.1': + cmd = "curl --insecure -4 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text" + ip = execShell(cmd) + result = ip[0].strip() + if result == '': + raise Exception("ipv4 is empty!") + writeFile(filename, result) + return result + return ipaddress + except Exception as e: + cmd = "curl --insecure -6 -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text" + ip = execShell(cmd) + result = ip[0].strip() + if result == '': + return '127.0.0.1' + writeFile(filename, result) + return result + finally: + pass + return '127.0.0.1' + + +def inArray(arrays, searchStr): + # 搜索数据中是否存在 + for key in arrays: + if key == searchStr: + return True + + return False def getJson(data): import json @@ -541,13 +570,6 @@ def isNumber(s): return False -def isRestart(): - # 检查是否允许重启 - num = M('tasks').where('status!=?', ('1',)).count() - if num > 0: - return False - return True - # 检查端口是否占用 def isOpenPort(port): import socket @@ -633,13 +655,33 @@ def deDoubleCrypt(key, strings): writeFileLog(getTracebackInfo()) return strings -# ------------------------------ openresty start ----------------------------- +# ------------------------------ panel start ----------------------------- + +def isRestart(): + # 检查是否允许重启 + num = M('tasks').where('status!=?', ('1',)).count() + if num > 0: + return False + return True + +def triggerTask(): + isTask = getPanelDir() + '/tmp/panelTask.pl' + writeFile(isTask, 'True') + +def restartTask(): + initd = getPanelDir() + '/scripts/init.d/mw' + if os.path.exists(initd): + cmd = initd + ' ' + 'restart_task' + os.system(cmd) + return True def restartMw(): restart_file = getPanelDir()+'/data/restart.pl' writeFile(restart_file, 'True') return True +# ------------------------------ panel end ----------------------------- +# ------------------------------ openresty start ----------------------------- def restartWeb(): return opWeb("reload") @@ -667,6 +709,7 @@ def opWeb(method): return True return False + def opLuaMake(cmd_name): path = getServerDir() + '/web_conf/nginx/lua/lua.conf' root_dir = getServerDir() + '/web_conf/nginx/lua/' + cmd_name diff --git a/web/static/app/public.js b/web/static/app/public.js index cb8eaae70..8516508d4 100755 --- a/web/static/app/public.js +++ b/web/static/app/public.js @@ -941,7 +941,7 @@ function removeTask(b) { time: 0, shade: [0.3, "#000"] }); - $.post("/files/remove_task", "id=" + b, function(c) { + $.post("/task/remove_task", "id=" + b, function(c) { layer.close(a); layer.msg(c.msg, { icon: c.status ? 1 : 5 diff --git a/web/thisdb/__init__.py b/web/thisdb/__init__.py new file mode 100644 index 000000000..ebaf86032 --- /dev/null +++ b/web/thisdb/__init__.py @@ -0,0 +1,11 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +from .option import * \ No newline at end of file diff --git a/web/thisdb/option.py b/web/thisdb/option.py new file mode 100644 index 000000000..1c197d1ce --- /dev/null +++ b/web/thisdb/option.py @@ -0,0 +1,28 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + + +import core.mw as mw + +def getOption(name, + type: str | None = 'common', + default : str | None = None +) -> str: + ''' + 获取配置的值 + :name -> str 名称 (必填) + :type -> str 类型 (可选|默认common) + :default -> str 默认值 (可选) + ''' + data = mw.M('option').field('name').where('name=? and type=?',(name, type,)).getField('value') + + if len(data) == 0: + return default + return data \ No newline at end of file diff --git a/web/utils/file.py b/web/utils/file.py index 4638252ef..56aa0a13a 100644 --- a/web/utils/file.py +++ b/web/utils/file.py @@ -397,4 +397,4 @@ def setMode(path): s_path = os.path.dirname(path) p_stat = os.stat(s_path) os.chown(path, p_stat.st_uid, p_stat.st_gid) - os.chmod(path, p_stat.st_mode) \ No newline at end of file + os.chmod(path, p_stat.st_mode) diff --git a/web/utils/task.py b/web/utils/task.py new file mode 100644 index 000000000..49e269647 --- /dev/null +++ b/web/utils/task.py @@ -0,0 +1,54 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import os +import pwd +import time + +import core.mw as mw + +# 删除进程下的所有进程 +def removeTaskRecursion(pid): + cmd = "ps -ef|grep %s | grep -v grep |sed -n '2,1p' | awk '{print $2}'" % pid + sub_pid = mw.execShell(cmd) + if sub_pid[0].strip() == '': + return 'ok' + + if sub_pid[0].strip() == pid : + return 'ok' + + removeTaskRecursion(sub_pid[0].strip()) + mw.execShell('kill -9 ' + sub_pid[0].strip()) + return sub_pid[0].strip() + +# 删除任务 +def removeTask(task_id): + try: + name = mw.M('tasks').where('id=?', (task_id,)).getField('name') + status = mw.M('tasks').where('id=?', (task_id,)).getField('status') + mw.M('tasks').delete(task_id) + if str(status) == '-1': + cmd = "ps aux | grep 'panel_task.py' | grep -v grep |awk '{print $2}'" + task_pid = mw.execShell(cmd) + task_list = task_pid[0].strip().split("\n") + for i in range(len(task_list)): + removeTaskRecursion(task_list[i]) + t = mw.execShell('kill -9 ' + task_list[i]) + print(t) + mw.triggerTask() + mw.restartTask() + except Exception as e: + mw.restartTask() + + # 删除日志 + task_log = mw.getPanelDir() + "/tmp/panelTask.pl" + if os.path.exists(task_log): + os.remove(task_log) + return mw.returnData(True, '任务已删除!') \ No newline at end of file