mirror of https://github.com/midoks/mdserver-web
commit
2438717c79
@ -0,0 +1,113 @@ |
||||
#!/bin/bash |
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin |
||||
DIR=$(cd "$(dirname "$0")"; pwd) |
||||
MDIR=$(dirname "$DIR") |
||||
|
||||
# echo $DIR |
||||
|
||||
PATH=$PATH:$DIR/bin |
||||
if [ -f ${DIR}/bin/activate ];then |
||||
source ${DIR}/bin/activate |
||||
|
||||
if [ "$?" != "0" ];then |
||||
echo "load local python env fail!" |
||||
fi |
||||
fi |
||||
|
||||
export LC_ALL="en_US.UTF-8" |
||||
|
||||
|
||||
mw_start_task() |
||||
{ |
||||
isStart=$(ps aux |grep 'panel_task.py'|grep -v grep|awk '{print $2}') |
||||
if [ "$isStart" == '' ];then |
||||
echo -e "starting mw-tasks... \c" |
||||
cd $DIR && python3 panel_task.py >> ${DIR}/logs/panel_task.log 2>&1 & |
||||
sleep 0.3 |
||||
isStart=$(ps aux |grep 'panel_task.py'|grep -v grep|awk '{print $2}') |
||||
if [ "$isStart" == '' ];then |
||||
echo -e "\033[31mfailed\033[0m" |
||||
echo '------------------------------------------------------' |
||||
tail -n 20 $DIR/logs/panel_task.log |
||||
echo '------------------------------------------------------' |
||||
echo -e "\033[31mError: mw-tasks service startup failed.\033[0m" |
||||
return; |
||||
fi |
||||
echo -e "\033[32mdone\033[0m" |
||||
else |
||||
echo "starting mw-tasks... mw-tasks (pid $(echo $isStart)) already running" |
||||
fi |
||||
} |
||||
|
||||
mw_start(){ |
||||
cd web && gunicorn -c setting.py app:app |
||||
#安全启动 |
||||
mw_start_task |
||||
} |
||||
|
||||
|
||||
mw_start_debug(){ |
||||
if [ ! -f $DIR/logs/panel_task.log ];then |
||||
echo '' > $DIR/logs/panel_task.log |
||||
fi |
||||
|
||||
python3 panel_task.py >> $DIR/logs/panel_task.log 2>&1 & |
||||
port=7200 |
||||
if [ -f /www/server/mdserver-web/data/port.pl ];then |
||||
port=$(cat /www/server/mdserver-web/data/port.pl) |
||||
fi |
||||
|
||||
if [ -f ${DIR}/data/port.pl ];then |
||||
port=$(cat ${DIR}/data/port.pl) |
||||
fi |
||||
# gunicorn -b :${port} -k gevent -w 1 app:app |
||||
cd web && gunicorn -b :${port} -w 1 app:app |
||||
} |
||||
|
||||
mw_start_debug2(){ |
||||
python3 panel_task.py >> $DIR/logs/panel_task.log 2>&1 & |
||||
gunicorn -b :7200 -w 1 app:app |
||||
} |
||||
|
||||
mw_start_debug3(){ |
||||
gunicorn -c setting.py app:app |
||||
python3 panel_task.py |
||||
} |
||||
|
||||
|
||||
mw_stop() |
||||
{ |
||||
PLIST=`ps -ef|grep app:app |grep -v grep|awk '{print $2}'` |
||||
for i in $PLIST |
||||
do |
||||
kill -9 $i > /dev/null 2>&1 |
||||
done |
||||
|
||||
pids=`ps -ef|grep panel_task.py | grep -v grep |awk '{print $2}'` |
||||
arr=($pids) |
||||
for p in ${arr[@]} |
||||
do |
||||
kill -9 $p > /dev/null 2>&1 |
||||
done |
||||
} |
||||
|
||||
case "$1" in |
||||
'start') mw_start;; |
||||
'stop') mw_stop;; |
||||
'restart') |
||||
mw_stop |
||||
mw_start |
||||
;; |
||||
'debug') |
||||
mw_stop |
||||
mw_start_debug |
||||
;; |
||||
'debug2') |
||||
mw_stop |
||||
mw_start_debug2 |
||||
;; |
||||
'debug3') |
||||
mw_stop |
||||
mw_start_debug3 |
||||
;; |
||||
esac |
@ -0,0 +1,626 @@ |
||||
# coding: utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# 计划任务 |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
import sys |
||||
import os |
||||
import json |
||||
import time |
||||
import threading |
||||
import psutil |
||||
|
||||
|
||||
web_dir = os.getcwd() + "/web" |
||||
os.chdir(web_dir) |
||||
sys.path.append(web_dir) |
||||
|
||||
from admin import app |
||||
from admin import model |
||||
|
||||
import core.mw as mw |
||||
import core.db as db |
||||
|
||||
|
||||
# print(mw.getPanelDir()) |
||||
|
||||
# print sys.path |
||||
|
||||
# cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\'' |
||||
# info = mw.execShell(cmd) |
||||
# p = "/usr/local/lib/" + info[0].strip() + "/site-packages" |
||||
# sys.path.append(p) |
||||
|
||||
|
||||
global pre, timeoutCount, logPath, isTask, oldEdate, isCheck |
||||
pre = 0 |
||||
timeoutCount = 0 |
||||
isCheck = 0 |
||||
oldEdate = None |
||||
|
||||
g_log_file = mw.getPanelTaskLog() |
||||
isTask = mw.getMWLogs() + '/panelTask.pl' |
||||
|
||||
if not os.path.exists(g_log_file): |
||||
os.system("touch " + g_log_file) |
||||
|
||||
def execShell(cmdstring, cwd=None, timeout=None, shell=True): |
||||
try: |
||||
global g_log_file |
||||
import shlex |
||||
import datetime |
||||
import subprocess |
||||
|
||||
if timeout: |
||||
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout) |
||||
|
||||
cmd = cmdstring + ' > ' + g_log_file + ' 2>&1' |
||||
sub = subprocess.Popen(cmd, cwd=cwd, stdin=subprocess.PIPE, shell=shell, bufsize=4096) |
||||
while sub.poll() is None: |
||||
time.sleep(0.1) |
||||
|
||||
data = sub.communicate() |
||||
# python3 fix 返回byte数据 |
||||
if isinstance(data[0], bytes): |
||||
t1 = str(data[0], encoding='utf-8') |
||||
|
||||
if isinstance(data[1], bytes): |
||||
t2 = str(data[1], encoding='utf-8') |
||||
return (t1, t2) |
||||
except Exception as e: |
||||
return (None, None) |
||||
|
||||
def service_cmd(method): |
||||
cmd = '/etc/init.d/mw' |
||||
if os.path.exists(cmd): |
||||
execShell(cmd + ' ' + method) |
||||
return |
||||
|
||||
cmd = mw.getRunDir() + '/scripts/init.d/mw' |
||||
if os.path.exists(cmd): |
||||
execShell(cmd + ' ' + method) |
||||
return |
||||
|
||||
|
||||
def openresty_cmd(method = 'reload'): |
||||
# 检查是否安装 |
||||
odir = mw.getServerDir() + '/openresty' |
||||
if not os.path.exists(odir): |
||||
return False |
||||
|
||||
# systemd |
||||
systemd = mw.systemdCfgDir()+'/openresty.service' |
||||
if os.path.exists(systemd): |
||||
execShell('systemctl ' + method + ' openresty') |
||||
return True |
||||
|
||||
sys_initd = '/etc/init.d/openresty' |
||||
if os.path.exists(sys_initd): |
||||
os.system(sys_initd + ' ' + method) |
||||
return True |
||||
|
||||
install_initd = mw.getServerDir()+'/openresty/init.d/openresty' |
||||
if os.path.exists(install_initd): |
||||
os.system(install_initd + ' ' + method) |
||||
return True |
||||
return False |
||||
|
||||
def mw_async(f): |
||||
def wrapper(*args, **kwargs): |
||||
thr = threading.Thread(target=f, args=args, kwargs=kwargs) |
||||
thr.start() |
||||
return wrapper |
||||
|
||||
|
||||
@mw_async |
||||
def restartMw(): |
||||
time.sleep(1) |
||||
cmd = mw.getRunDir() + '/scripts/init.d/mw reload &' |
||||
mw.execShell(cmd) |
||||
|
||||
|
||||
|
||||
def downloadFile(url, filename): |
||||
# 下载文件 |
||||
try: |
||||
import urllib |
||||
import socket |
||||
socket.setdefaulttimeout(300) |
||||
|
||||
headers = ('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36') |
||||
opener = urllib.request.build_opener() |
||||
opener.addheaders = [headers] |
||||
urllib.request.install_opener(opener) |
||||
|
||||
urllib.request.urlretrieve(url, filename=filename, reporthook=downloadHook) |
||||
|
||||
if not mw.isAppleSystem(): |
||||
os.system('chown www.www ' + filename) |
||||
|
||||
writeLogs('done') |
||||
except Exception as e: |
||||
writeLogs(str(e)) |
||||
return True |
||||
|
||||
|
||||
def downloadHook(count, blockSize, totalSize): |
||||
# 下载文件进度回调 |
||||
global pre |
||||
used = count * blockSize |
||||
pre1 = int((100.0 * used / totalSize)) |
||||
if pre == (100 - pre1): |
||||
return |
||||
speed = {'total': totalSize, 'used': used, 'pre': pre1} |
||||
writeLogs(json.dumps(speed)) |
||||
|
||||
|
||||
def writeLogs(data): |
||||
# 写输出日志 |
||||
try: |
||||
fp = open(g_log_file, 'w+') |
||||
fp.write(data) |
||||
fp.close() |
||||
except: |
||||
pass |
||||
|
||||
|
||||
def runPanelTask(): |
||||
try: |
||||
bash_list = model.getTaskList(status=-1) |
||||
for task in bash_list: |
||||
model.setTaskStatus(task['id'], 0) |
||||
|
||||
run_list = model.getTaskList(status=0) |
||||
for run_task in run_list: |
||||
start = int(time.time()) |
||||
model.setTaskData(run_task['id'], start=start) |
||||
model.setTaskStatus(run_task['id'], -1) |
||||
if run_task['type'] == 'download': |
||||
argv = run_task['cmd'].split('|mw|') |
||||
downloadFile(argv[0], argv[1]) |
||||
elif run_task['type'] == 'execshell': |
||||
execShell(run_task['cmd']) |
||||
end = int(time.time()) |
||||
model.setTaskData(run_task['id'], end=end) |
||||
model.setTaskStatus(run_task['id'], 1) |
||||
except Exception as e: |
||||
print(str(e)) |
||||
|
||||
# 站点过期检查 |
||||
# siteEdate() |
||||
|
||||
# 任务队列 |
||||
def startPanelTask(): |
||||
try: |
||||
while True: |
||||
runPanelTask() |
||||
time.sleep(1) |
||||
except Exception as e: |
||||
print(str(e)) |
||||
time.sleep(10) |
||||
startPanelTask() |
||||
|
||||
# 网站到期处理 |
||||
def siteEdate(): |
||||
global oldEdate |
||||
try: |
||||
if not oldEdate: |
||||
oldEdate = mw.readFile('data/edate.pl') |
||||
if not oldEdate: |
||||
oldEdate = '0000-00-00' |
||||
mEdate = time.strftime('%Y-%m-%d', time.localtime()) |
||||
if oldEdate == mEdate: |
||||
return False |
||||
edateSites = mw.M('sites').where('edate>? AND edate<? AND (status=? OR status=?)', |
||||
('0000-00-00', mEdate, 1, '正在运行')).field('id,name').select() |
||||
import site_api |
||||
for site in edateSites: |
||||
site_api.site_api().stop(site['id'], site['name']) |
||||
oldEdate = mEdate |
||||
mw.writeFile('data/edate.pl', mEdate) |
||||
except Exception as e: |
||||
print(str(e)) |
||||
|
||||
|
||||
def systemTask(): |
||||
# 系统监控任务 |
||||
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<?", (deltime,)).delete() |
||||
|
||||
data = (networkInfo['up'] / 5, networkInfo['down'] / 5, networkInfo['upTotal'], networkInfo[ |
||||
'downTotal'], networkInfo['downPackets'], networkInfo['upPackets'], addtime) |
||||
sql.table('network').add( |
||||
'up,down,total_up,total_down,down_packets,up_packets,addtime', data) |
||||
sql.table('network').where( |
||||
"addtime<?", (deltime,)).delete() |
||||
# if os.path.exists('/proc/diskstats'): |
||||
data = (diskInfo['read_count'], diskInfo['write_count'], diskInfo['read_bytes'], diskInfo[ |
||||
'write_bytes'], diskInfo['read_time'], diskInfo['write_time'], addtime) |
||||
sql.table('diskio').add( |
||||
'read_count,write_count,read_bytes,write_bytes,read_time,write_time,addtime', data) |
||||
sql.table('diskio').where( |
||||
"addtime<?", (deltime,)).delete() |
||||
|
||||
# LoadAverage |
||||
load_average = sm.getLoadAverage() |
||||
lpro = round( |
||||
(load_average['one'] / load_average['max']) * 100, 2) |
||||
if lpro > 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() |
||||
|
||||
|
||||
# -------------------------------------- PHP监控 start --------------------------------------------- # |
||||
# 502错误检查线程 |
||||
def check502Task(): |
||||
try: |
||||
while True: |
||||
if os.path.exists(mw.getPanelDir() + '/data/502Task.pl'): |
||||
check502() |
||||
time.sleep(30) |
||||
except: |
||||
time.sleep(30) |
||||
check502Task() |
||||
|
||||
|
||||
def check502(): |
||||
try: |
||||
verlist = [ |
||||
'52', '53', '54', '55', '56', '70', |
||||
'71', '72', '73', '74', '80', '81', |
||||
'82', '83', '84' |
||||
] |
||||
for ver in verlist: |
||||
sdir = mw.getServerDir() |
||||
php_path = sdir + '/php/' + ver + '/sbin/php-fpm' |
||||
if not os.path.exists(php_path): |
||||
continue |
||||
if checkPHPVersion(ver): |
||||
continue |
||||
if startPHPVersion(ver): |
||||
print('检测到PHP-' + ver + '处理异常,已自动修复!') |
||||
mw.writeLog('PHP守护程序', '检测到PHP-' + ver + '处理异常,已自动修复!') |
||||
except Exception as e: |
||||
print(str(e)) |
||||
|
||||
|
||||
# 处理指定PHP版本 |
||||
def startPHPVersion(version): |
||||
sdir = mw.getServerDir() |
||||
try: |
||||
# system |
||||
phpService = mw.systemdCfgDir() + '/php' + version + '.service' |
||||
if os.path.exists(phpService): |
||||
mw.execShell("systemctl restart php" + version) |
||||
if checkPHPVersion(version): |
||||
return True |
||||
|
||||
# initd |
||||
fpm = sdir + '/php/init.d/php' + version |
||||
php_path = sdir + '/php/' + version + '/sbin/php-fpm' |
||||
if not os.path.exists(php_path): |
||||
if os.path.exists(fpm): |
||||
os.remove(fpm) |
||||
return False |
||||
|
||||
if not os.path.exists(fpm): |
||||
return False |
||||
|
||||
# 尝试重载服务 |
||||
os.system(fpm + ' reload') |
||||
if checkPHPVersion(version): |
||||
return True |
||||
|
||||
# 尝试重启服务 |
||||
cgi = '/tmp/php-cgi-' + version + '.sock' |
||||
pid = sdir + '/php/' + version + '/var/run/php-fpm.pid' |
||||
data = mw.execShell("ps -ef | grep php/" + version +" | grep -v grep|grep -v python |awk '{print $2}'") |
||||
if data[0] != '': |
||||
os.system("ps -ef | grep php/" + version + " | grep -v grep|grep -v python |awk '{print $2}' | xargs kill ") |
||||
time.sleep(0.5) |
||||
if not os.path.exists(cgi): |
||||
os.system('rm -f ' + cgi) |
||||
if not os.path.exists(pid): |
||||
os.system('rm -f ' + pid) |
||||
os.system(fpm + ' start') |
||||
if checkPHPVersion(version): |
||||
return True |
||||
|
||||
# 检查是否正确启动 |
||||
if os.path.exists(cgi): |
||||
return True |
||||
except Exception as e: |
||||
print(str(e)) |
||||
return True |
||||
|
||||
|
||||
def getFpmConfFile(version): |
||||
return mw.getServerDir() + '/php/' + version + '/etc/php-fpm.d/www.conf' |
||||
|
||||
|
||||
def getFpmAddress(version): |
||||
fpm_address = '/tmp/php-cgi-{}.sock'.format(version) |
||||
php_fpm_file = getFpmConfFile(version) |
||||
try: |
||||
content = readFile(php_fpm_file) |
||||
tmp = re.findall(r"listen\s*=\s*(.+)", content) |
||||
if not tmp: |
||||
return fpm_address |
||||
if tmp[0].find('sock') != -1: |
||||
return fpm_address |
||||
if tmp[0].find(':') != -1: |
||||
listen_tmp = tmp[0].split(':') |
||||
if bind: |
||||
fpm_address = (listen_tmp[0], int(listen_tmp[1])) |
||||
else: |
||||
fpm_address = ('127.0.0.1', int(listen_tmp[1])) |
||||
else: |
||||
fpm_address = ('127.0.0.1', int(tmp[0])) |
||||
return fpm_address |
||||
except: |
||||
return fpm_address |
||||
|
||||
|
||||
def checkPHPVersion(version): |
||||
# 检查指定PHP版本 |
||||
try: |
||||
sock = getFpmAddress(version) |
||||
data = mw.requestFcgiPHP(sock, '/phpfpm_status_' + version + '?json') |
||||
result = str(data, encoding='utf-8') |
||||
except Exception as e: |
||||
result = 'Bad Gateway' |
||||
|
||||
# print(version,result) |
||||
# 检查openresty |
||||
if result.find('Bad Gateway') != -1: |
||||
return False |
||||
if result.find('HTTP Error 404: Not Found') != -1: |
||||
return False |
||||
|
||||
# 检查Web服务是否启动 |
||||
if result.find('Connection refused') != -1: |
||||
return False |
||||
# global isTask |
||||
# if os.path.exists(isTask): |
||||
# isStatus = mw.readFile(isTask) |
||||
# if isStatus == 'True': |
||||
# return True |
||||
|
||||
# # systemd |
||||
# systemd = mw.systemdCfgDir() + '/openresty.service' |
||||
# if os.path.exists(systemd): |
||||
# execShell('systemctl reload openresty') |
||||
# return True |
||||
# # initd |
||||
# initd = '/etc/init.d/openresty' |
||||
# if os.path.exists(initd): |
||||
# os.system(initd + ' reload') |
||||
return True |
||||
|
||||
# --------------------------------------PHP监控 end--------------------------------------------- # |
||||
|
||||
|
||||
# --------------------------------------OpenResty Auto Restart Start --------------------------------------------- # |
||||
# 解决acme.sh续签后,未起效。 |
||||
def openrestyAutoRestart(): |
||||
try: |
||||
while True: |
||||
# 检查是否安装 |
||||
odir = mw.getServerDir() + '/openresty' |
||||
if not os.path.exists(odir): |
||||
time.sleep(86400) |
||||
continue |
||||
|
||||
openresty_cmd('reload') |
||||
time.sleep(86400) |
||||
except Exception as e: |
||||
print(str(e)) |
||||
time.sleep(86400) |
||||
|
||||
# --------------------------------------OpenResty Auto Restart End --------------------------------------------- # |
||||
|
||||
# ------------------------------------ OpenResty Restart At Once Start ------------------------------------------ # |
||||
|
||||
|
||||
def openrestyRestartAtOnce(): |
||||
restart_nginx_tip = 'data/restart_nginx.pl' |
||||
while True: |
||||
if os.path.exists(restart_nginx_tip): |
||||
os.remove(restart_nginx_tip) |
||||
openresty_cmd('reload') |
||||
time.sleep(1) |
||||
# ----------------------------------- OpenResty Restart At Once End ------------------------------------------ # |
||||
|
||||
|
||||
# --------------------------------------Panel Restart Start --------------------------------------------- # |
||||
def restartPanelService(): |
||||
restartTip = 'data/restart.pl' |
||||
while True: |
||||
if os.path.exists(restartTip): |
||||
os.remove(restartTip) |
||||
service_cmd('restart_panel') |
||||
time.sleep(1) |
||||
# --------------------------------------Panel Restart End --------------------------------------------- # |
||||
|
||||
|
||||
def setDaemon(t): |
||||
if sys.version_info.major == 3 and sys.version_info.minor >= 10: |
||||
t.daemon = True |
||||
else: |
||||
t.setDaemon(True) |
||||
return t |
||||
|
||||
def run(): |
||||
# # 系统监控 |
||||
# sysTask = threading.Thread(target=systemTask) |
||||
# sysTask = setDaemon(sysTask) |
||||
# sysTask.start() |
||||
|
||||
# # PHP 502错误检查线程 |
||||
# php502 = threading.Thread(target=check502Task) |
||||
# php502 = setDaemon(php502) |
||||
# php502.start() |
||||
|
||||
# # OpenResty Restart At Once Start |
||||
# oraos = threading.Thread(target=openrestyRestartAtOnce) |
||||
# oraos = setDaemon(oraos) |
||||
# oraos.start() |
||||
|
||||
|
||||
# # OpenResty Auto Restart Start |
||||
# oar = threading.Thread(target=openrestyAutoRestart) |
||||
# oar = setDaemon(oar) |
||||
# oar.start() |
||||
|
||||
|
||||
# # Panel Restart Start |
||||
# rps = threading.Thread(target=restartPanelService) |
||||
# rps = setDaemon(rps) |
||||
# rps.start() |
||||
|
||||
# 面板后台任务 |
||||
startPanelTask() |
||||
|
||||
if __name__ == "__main__": |
||||
with app.app_context(): |
||||
run() |
||||
|
@ -0,0 +1,306 @@ |
||||
# coding=utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# 工具箱 |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
|
||||
import sys |
||||
import os |
||||
import json |
||||
import time |
||||
import re |
||||
|
||||
web_dir = os.getcwd() + "/web" |
||||
os.chdir(web_dir) |
||||
sys.path.append(web_dir) |
||||
|
||||
import core.mw as mw |
||||
import core.db as db |
||||
|
||||
# cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\'' |
||||
# info = mw.execShell(cmd) |
||||
# p = "/usr/local/lib/" + info[0].strip() + "/site-packages" |
||||
# sys.path.append(p) |
||||
|
||||
INIT_DIR = "/etc/rc.d/init.d" |
||||
if mw.isAppleSystem(): |
||||
INIT_DIR = mw.getPanelDir() + "/scripts/init.d" |
||||
|
||||
INIT_CMD = INIT_DIR + "/mw" |
||||
|
||||
|
||||
def mw_input_cmd(msg): |
||||
if sys.version_info[0] == 2: |
||||
in_val = raw_input(msg) |
||||
else: |
||||
in_val = input(msg) |
||||
return in_val |
||||
|
||||
|
||||
def mwcli(mw_input=0): |
||||
raw_tip = "======================================================" |
||||
if not mw_input: |
||||
print("===============mdserver-web cli tools=================") |
||||
print("(1) 重启面板服务") |
||||
print("(2) 停止面板服务") |
||||
print("(3) 启动面板服务") |
||||
print("(4) 重载面板服务") |
||||
print("(5) 修改面板端口") |
||||
print("(10) 查看面板默认信息") |
||||
print("(11) 修改面板密码") |
||||
print("(12) 修改面板用户名") |
||||
print("(13) 显示面板错误日志") |
||||
print("(20) 关闭BasicAuth认证") |
||||
print("(21) 解除域名绑定") |
||||
print("(22) 解除面板SSL绑定") |
||||
print("(23) 开启IPV6支持") |
||||
print("(24) 关闭IPV6支持") |
||||
print("(25) 开启防火墙SSH端口") |
||||
print("(26) 关闭二次验证") |
||||
print("(27) 查看防火墙信息") |
||||
print("(100) 开启PHP52显示") |
||||
print("(101) 关闭PHP52显示") |
||||
print("(200) 切换Linux系统软件源") |
||||
print("(201) 简单速度测试") |
||||
print("(0) 取消") |
||||
print(raw_tip) |
||||
try: |
||||
mw_input = input("请输入命令编号:") |
||||
if sys.version_info[0] == 3: |
||||
mw_input = int(mw_input) |
||||
except: |
||||
mw_input = 0 |
||||
|
||||
nums = [ |
||||
1, 2, 3, 4, 5, 10, 11, 12, 13, |
||||
20, 21, 22, 23, 24, 25, 26, 27, |
||||
100, 101, |
||||
200, 201 |
||||
] |
||||
if not mw_input in nums: |
||||
print(raw_tip) |
||||
print("已取消!") |
||||
exit() |
||||
|
||||
if mw_input == 1: |
||||
os.system(INIT_CMD + " restart") |
||||
elif mw_input == 2: |
||||
os.system(INIT_CMD + " stop") |
||||
elif mw_input == 3: |
||||
os.system(INIT_CMD + " start") |
||||
elif mw_input == 4: |
||||
os.system(INIT_CMD + " reload") |
||||
elif mw_input == 5: |
||||
in_port = mw_input_cmd("请输入新的面板端口:") |
||||
in_port_int = int(in_port.strip()) |
||||
if in_port_int < 65536 and in_port_int > 0: |
||||
import firewall_api |
||||
firewall_api.firewall_api().addAcceptPortArgs( |
||||
in_port, 'WEB面板[TOOLS修改]', 'port') |
||||
mw.writeFile('data/port.pl', in_port) |
||||
os.system(INIT_CMD + " restart_panel") |
||||
os.system(INIT_CMD + " default") |
||||
else: |
||||
print("|-端口范围在0-65536之间") |
||||
return |
||||
elif mw_input == 10: |
||||
os.system(INIT_CMD + " default") |
||||
elif mw_input == 11: |
||||
input_pwd = mw_input_cmd("请输入新的面板密码:") |
||||
if len(input_pwd.strip()) < 5: |
||||
print("|-错误,密码长度不能小于5位") |
||||
return |
||||
set_panel_pwd(input_pwd.strip(), True) |
||||
elif mw_input == 12: |
||||
input_user = mw_input_cmd("请输入新的面板用户名(>=5位):") |
||||
set_panel_username(input_user.strip()) |
||||
elif mw_input == 13: |
||||
os.system('tail -100 ' + mw.getPanelDir() + '/logs/error.log') |
||||
elif mw_input == 20: |
||||
basic_auth = 'data/basic_auth.json' |
||||
if os.path.exists(basic_auth): |
||||
os.remove(basic_auth) |
||||
os.system(INIT_CMD + " restart") |
||||
print("|-关闭basic_auth成功") |
||||
elif mw_input == 21: |
||||
bind_domain = 'data/bind_domain.pl' |
||||
if os.path.exists(bind_domain): |
||||
os.remove(bind_domain) |
||||
os.system(INIT_CMD + " unbind_domain") |
||||
print("|-解除域名绑定成功") |
||||
elif mw_input == 22: |
||||
ssl_choose = 'ssl/choose.pl' |
||||
if os.path.exists(ssl_choose): |
||||
os.remove(ssl_choose) |
||||
os.system(INIT_CMD + " unbind_ssl") |
||||
print("|-解除面板SSL绑定成功") |
||||
elif mw_input == 23: |
||||
listen_ipv6 = 'data/ipv6.pl' |
||||
if not os.path.exists(listen_ipv6): |
||||
mw.writeFile(listen_ipv6,'True') |
||||
os.system(INIT_CMD + " restart") |
||||
print("|-开启IPv6支持了") |
||||
else: |
||||
print("|-已开启IPv6支持!") |
||||
elif mw_input == 24: |
||||
listen_ipv6 = 'data/ipv6.pl' |
||||
if not os.path.exists(listen_ipv6): |
||||
print("|-已关闭IPv6支持!") |
||||
else: |
||||
os.remove(listen_ipv6) |
||||
os.system(INIT_CMD + " restart") |
||||
print("|-关闭IPv6支持了") |
||||
elif mw_input == 25: |
||||
open_ssh_port() |
||||
print("|-已开启!") |
||||
elif mw_input == 26: |
||||
auth_secret = 'data/auth_secret.pl' |
||||
if os.path.exists(auth_secret): |
||||
os.remove(auth_secret) |
||||
print("|-关闭二次验证成功!") |
||||
else: |
||||
print("|-二次验证已关闭!") |
||||
elif mw_input == 27: |
||||
cmd = 'which ufw' |
||||
run_cmd = False |
||||
find_cmd = mw.execShell(cmd) |
||||
if find_cmd[0].strip() != '': |
||||
run_cmd = True |
||||
os.system('ufw status') |
||||
|
||||
cmd = 'which firewall-cmd' |
||||
find_cmd = mw.execShell(cmd) |
||||
if find_cmd[0].strip() != '': |
||||
run_cmd = True |
||||
os.system('firewall-cmd --list-all') |
||||
if not run_cmd: |
||||
mw.echoInfo("未检测到防火墙!") |
||||
elif mw_input == 100: |
||||
php_conf = 'plugins/php/info.json' |
||||
if os.path.exists(php_conf): |
||||
cont = mw.readFile(php_conf) |
||||
cont = re.sub("\"53\"", "\"52\",\"53\"", cont) |
||||
cont = re.sub("\"5.3.29\"", "\"5.2.17\",\"5.3.29\"", cont) |
||||
mw.writeFile(php_conf, cont) |
||||
print("|-执行PHP52显示成功!") |
||||
elif mw_input == 101: |
||||
php_conf = 'plugins/php/info.json' |
||||
if os.path.exists(php_conf): |
||||
cont = mw.readFile(php_conf) |
||||
cont = re.sub("\"52\",", "", cont) |
||||
cont = re.sub("\"5.2.17\",", cont) |
||||
mw.writeFile(php_conf, cont) |
||||
print("|-执行PHP52隐藏成功!") |
||||
elif mw_input == 200: |
||||
os.system(INIT_CMD + " mirror") |
||||
elif mw_input == 201: |
||||
os.system('curl -Lso- bench.sh | bash') |
||||
|
||||
|
||||
def open_ssh_port(): |
||||
import firewall_api |
||||
find_ssh_port_cmd = "cat /etc/ssh/sshd_config | grep '^Port \\d*' | tail -1" |
||||
cmd_data = mw.execShell(find_ssh_port_cmd) |
||||
ssh_port = cmd_data[0].replace("Port ", '').strip() |
||||
if ssh_port == '': |
||||
ssh_port = '22' |
||||
|
||||
print("|-SSH端口: "+ str(ssh_port)) |
||||
firewall_api.firewall_api().addAcceptPortArgs(ssh_port, 'SSH远程管理服务', 'port') |
||||
return True |
||||
|
||||
|
||||
def set_panel_pwd(password, ncli=False): |
||||
# 设置面板密码 |
||||
import db |
||||
sql = db.Sql() |
||||
result = sql.table('users').where('id=?', (1,)).setField( |
||||
'password', mw.md5(password)) |
||||
username = sql.table('users').where('id=?', (1,)).getField('username') |
||||
if ncli: |
||||
print("|-用户名: " + username) |
||||
print("|-新密码: " + password) |
||||
else: |
||||
print(username) |
||||
|
||||
|
||||
def show_panel_pwd(): |
||||
# 设置面板密码 |
||||
import db |
||||
sql = db.Sql() |
||||
password = sql.table('users').where('id=?', (1,)).getField('password') |
||||
|
||||
file_pwd = '' |
||||
if os.path.exists('data/default.pl'): |
||||
file_pwd = mw.readFile('data/default.pl').strip() |
||||
|
||||
if mw.md5(file_pwd) == password: |
||||
print('password: ' + file_pwd) |
||||
return |
||||
print("password has been changed!") |
||||
|
||||
|
||||
def set_panel_username(username=None): |
||||
# 随机面板用户名 |
||||
import db |
||||
sql = db.Sql() |
||||
if username: |
||||
if len(username) < 5: |
||||
print("|-错误,用户名长度不能少于5位") |
||||
return |
||||
if username in ['admin', 'root']: |
||||
print("|-错误,不能使用过于简单的用户名") |
||||
return |
||||
|
||||
sql.table('users').where('id=?', (1,)).setField('username', username) |
||||
print("|-新用户名: %s" % username) |
||||
return |
||||
|
||||
username = sql.table('users').where('id=?', (1,)).getField('username') |
||||
if username == 'admin': |
||||
username = mw.getRandomString(8).lower() |
||||
sql.table('users').where('id=?', (1,)).setField('username', username) |
||||
print('username: ' + username) |
||||
|
||||
|
||||
def getServerIp(): |
||||
version = sys.argv[2] |
||||
# ip = mw.execShell( |
||||
# "curl --insecure -{} -sS --connect-timeout 5 -m 60 https://v6r.ipip.net/?format=text".format(version)) |
||||
ip = mw.execShell( |
||||
"curl --insecure -{} -sS --connect-timeout 5 -m 60 https://ip.cachecha.com/?format=text".format(version)) |
||||
print(ip[0]) |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
method = sys.argv[1] |
||||
if method == 'panel': |
||||
set_panel_pwd(sys.argv[2]) |
||||
elif method == 'username': |
||||
if len(sys.argv) > 2: |
||||
set_panel_username(sys.argv[2]) |
||||
else: |
||||
set_panel_username() |
||||
elif method == 'password': |
||||
show_panel_pwd() |
||||
elif method == 'getServerIp': |
||||
getServerIp() |
||||
elif method == "cli": |
||||
clinum = 0 |
||||
try: |
||||
if len(sys.argv) > 2: |
||||
clinum = int(sys.argv[2]) if sys.argv[2][:6] else sys.argv[2] |
||||
except: |
||||
clinum = sys.argv[2] |
||||
mwcli(clinum) |
||||
else: |
||||
print('ERROR: Parameter error') |
After Width: | Height: | Size: 42 KiB |
@ -0,0 +1,31 @@ |
||||
<style> |
||||
.overflow_hide { |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
white-space: nowrap; |
||||
vertical-align: middle; |
||||
} |
||||
</style> |
||||
|
||||
<div class="bt-form"> |
||||
<div class='plugin_version'></div> |
||||
<div class="bt-w-main"> |
||||
<div class="bt-w-menu"> |
||||
<p class="bgw" onclick="pluginService('alist');">服务</p> |
||||
<p onclick="pluginInitD('alist');">自启动</p> |
||||
<p onclick="alistCommonFunc();">常用功能</p> |
||||
<p onclick="pluginConfigTpl('alist',$('.plugin_version').attr('version'));">配置修改</p> |
||||
<p onclick="pluginLogs('alist','','run_log');">运行日志</p> |
||||
<p onclick="alistReadme();">相关说明</p> |
||||
|
||||
</div> |
||||
<div class="bt-w-con pd15"> |
||||
<div class="soft-man-con" style="height: 520px; overflow: auto;"></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<script type="text/javascript"> |
||||
$.getScript( "/plugins/file?name=alist&f=js/alist.js", function(){ |
||||
pluginService('alist', $('.plugin_version').attr('version')); |
||||
}); |
||||
</script> |
@ -0,0 +1,292 @@ |
||||
# coding:utf-8 |
||||
|
||||
import sys |
||||
import io |
||||
import os |
||||
import time |
||||
import re |
||||
|
||||
sys.path.append(os.getcwd() + "/class/core") |
||||
import mw |
||||
|
||||
app_debug = False |
||||
if mw.isAppleSystem(): |
||||
app_debug = True |
||||
|
||||
|
||||
def getPluginName(): |
||||
return 'alist' |
||||
|
||||
|
||||
def getPluginDir(): |
||||
return mw.getPluginDir() + '/' + getPluginName() |
||||
|
||||
|
||||
def getServerDir(): |
||||
return mw.getServerDir() + '/' + getPluginName() |
||||
|
||||
|
||||
def getInitDFile(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return '/tmp/' + getPluginName() |
||||
|
||||
if current_os.startswith('freebsd'): |
||||
return '/etc/rc.d/' + getPluginName() |
||||
|
||||
return '/etc/init.d/' + getPluginName() |
||||
|
||||
|
||||
def getInitDTpl(): |
||||
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl" |
||||
return path |
||||
|
||||
|
||||
def getArgs(): |
||||
args = sys.argv[3:] |
||||
tmp = {} |
||||
args_len = len(args) |
||||
|
||||
if args_len == 1: |
||||
t = args[0].strip('{').strip('}') |
||||
if t.strip() == '': |
||||
tmp = [] |
||||
else: |
||||
t = t.split(':') |
||||
tmp[t[0]] = t[1] |
||||
tmp[t[0]] = t[1] |
||||
elif args_len > 1: |
||||
for i in range(len(args)): |
||||
t = args[i].split(':') |
||||
tmp[t[0]] = t[1] |
||||
return tmp |
||||
|
||||
def checkArgs(data, ck=[]): |
||||
for i in range(len(ck)): |
||||
if not ck[i] in data: |
||||
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) |
||||
return (True, mw.returnJson(True, 'ok')) |
||||
|
||||
|
||||
def getConf(): |
||||
path = getServerDir() + "/data/config.json" |
||||
return path |
||||
|
||||
def configTpl(): |
||||
path = getPluginDir() + '/tpl' |
||||
pathFile = os.listdir(path) |
||||
tmp = [] |
||||
for one in pathFile: |
||||
file = path + '/' + one |
||||
tmp.append(file) |
||||
return mw.getJson(tmp) |
||||
|
||||
|
||||
def readConfigTpl(): |
||||
args = getArgs() |
||||
data = checkArgs(args, ['file']) |
||||
if not data[0]: |
||||
return data[1] |
||||
|
||||
content = mw.readFile(args['file']) |
||||
content = contentReplace(content) |
||||
return mw.returnJson(True, 'ok', content) |
||||
|
||||
|
||||
def status(): |
||||
data = mw.execShell( |
||||
"ps aux|grep alist |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'") |
||||
|
||||
if data[0] == '': |
||||
return 'stop' |
||||
return 'start' |
||||
|
||||
def contentReplace(content): |
||||
service_path = mw.getServerDir() |
||||
content = content.replace('{$ROOT_PATH}', mw.getRootDir()) |
||||
content = content.replace('{$SERVER_PATH}', service_path) |
||||
content = content.replace('{$SERVER_APP}', service_path + '/'+getPluginName()) |
||||
return content |
||||
|
||||
def initDreplace(): |
||||
|
||||
file_tpl = getInitDTpl() |
||||
service_path = os.path.dirname(os.getcwd()) |
||||
|
||||
initD_path = getServerDir() + '/init.d' |
||||
if not os.path.exists(initD_path): |
||||
os.mkdir(initD_path) |
||||
file_bin = initD_path + '/' + getPluginName() |
||||
|
||||
# initd replace |
||||
if not os.path.exists(file_bin): |
||||
content = mw.readFile(file_tpl) |
||||
content = content.replace('{$SERVER_PATH}', service_path) |
||||
mw.writeFile(file_bin, content) |
||||
mw.execShell('chmod +x ' + file_bin) |
||||
|
||||
# systemd |
||||
systemDir = mw.systemdCfgDir() |
||||
systemService = systemDir + '/' + getPluginName() + '.service' |
||||
if os.path.exists(systemDir) and not os.path.exists(systemService): |
||||
systemServiceTpl = getPluginDir() + '/init.d/' + getPluginName() + '.service.tpl' |
||||
service_path = mw.getServerDir() |
||||
se_content = mw.readFile(systemServiceTpl) |
||||
se_content = se_content.replace('{$SERVER_PATH}', service_path) |
||||
mw.writeFile(systemService, se_content) |
||||
mw.execShell('systemctl daemon-reload') |
||||
|
||||
return file_bin |
||||
|
||||
|
||||
def alistOp(method): |
||||
file = initDreplace() |
||||
|
||||
current_os = mw.getOs() |
||||
if current_os == "darwin": |
||||
data = mw.execShell(file + ' ' + method) |
||||
if data[1] == '': |
||||
return 'ok' |
||||
return data[1] |
||||
|
||||
if current_os.startswith("freebsd"): |
||||
data = mw.execShell('service ' + getPluginName() + ' ' + method) |
||||
if data[1] == '': |
||||
return 'ok' |
||||
return data[1] |
||||
|
||||
data = mw.execShell('systemctl ' + method + ' ' + getPluginName()) |
||||
if data[1] == '': |
||||
return 'ok' |
||||
return data[1] |
||||
|
||||
|
||||
def start(): |
||||
return alistOp('start') |
||||
|
||||
|
||||
def stop(): |
||||
return alistOp('stop') |
||||
|
||||
|
||||
def restart(): |
||||
status = alistOp('restart') |
||||
return status |
||||
|
||||
|
||||
def reload(): |
||||
return alistOp('reload') |
||||
|
||||
|
||||
def initdStatus(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return "Apple Computer does not support" |
||||
|
||||
if current_os.startswith('freebsd'): |
||||
initd_bin = getInitDFile() |
||||
if os.path.exists(initd_bin): |
||||
return 'ok' |
||||
|
||||
shell_cmd = 'systemctl status ' + \ |
||||
getPluginName() + ' | grep loaded | grep "enabled;"' |
||||
data = mw.execShell(shell_cmd) |
||||
if data[0] == '': |
||||
return 'fail' |
||||
return 'ok' |
||||
|
||||
|
||||
def initdInstall(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return "Apple Computer does not support" |
||||
|
||||
# freebsd initd install |
||||
if current_os.startswith('freebsd'): |
||||
import shutil |
||||
source_bin = initDreplace() |
||||
initd_bin = getInitDFile() |
||||
shutil.copyfile(source_bin, initd_bin) |
||||
mw.execShell('chmod +x ' + initd_bin) |
||||
mw.execShell('sysrc ' + getPluginName() + '_enable="YES"') |
||||
return 'ok' |
||||
|
||||
mw.execShell('systemctl enable ' + getPluginName()) |
||||
return 'ok' |
||||
|
||||
|
||||
def initdUinstall(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return "Apple Computer does not support" |
||||
|
||||
if current_os.startswith('freebsd'): |
||||
initd_bin = getInitDFile() |
||||
os.remove(initd_bin) |
||||
mw.execShell('sysrc ' + getPluginName() + '_enable="NO"') |
||||
return 'ok' |
||||
|
||||
mw.execShell('systemctl disable ' + getPluginName()) |
||||
return 'ok' |
||||
|
||||
|
||||
def runLog(): |
||||
return getServerDir() + '/data/log/log.log' |
||||
|
||||
def pSqliteDb(dbname='databases'): |
||||
pos_file = getServerDir() + '/data/' |
||||
file = pos_file + '/data.db' |
||||
name = 'data' |
||||
conn = mw.M(dbname).dbPos(pos_file, name) |
||||
return conn |
||||
|
||||
def clearCopyTask(): |
||||
conn = pSqliteDb('x_task_items') |
||||
conn.where('key=?', ('copy',)).setField('persist_data','[]') |
||||
restart() |
||||
return mw.returnJson(True, '清空成功并重启服务!') |
||||
|
||||
def homePage(): |
||||
import json |
||||
content = mw.readFile(getConf()) |
||||
data = json.loads(content) |
||||
http_port = data['scheme']['http_port'] |
||||
ip = mw.getLocalIp() |
||||
if mw.isAppleSystem(): |
||||
ip = '127.0.0.1' |
||||
url = 'http://'+ip+":"+str(http_port) |
||||
# print(url) |
||||
return mw.returnJson(True, 'ok!', url) |
||||
|
||||
if __name__ == "__main__": |
||||
func = sys.argv[1] |
||||
if func == 'status': |
||||
print(status()) |
||||
elif func == 'start': |
||||
print(start()) |
||||
elif func == 'stop': |
||||
print(stop()) |
||||
elif func == 'restart': |
||||
print(restart()) |
||||
elif func == 'reload': |
||||
print(reload()) |
||||
elif func == 'initd_status': |
||||
print(initdStatus()) |
||||
elif func == 'initd_install': |
||||
print(initdInstall()) |
||||
elif func == 'initd_uninstall': |
||||
print(initdUinstall()) |
||||
elif func == 'conf': |
||||
print(getConf()) |
||||
elif func == 'run_log': |
||||
print(runLog()) |
||||
elif func == 'config_tpl': |
||||
print(configTpl()) |
||||
elif func == 'read_config_tpl': |
||||
print(readConfigTpl()) |
||||
elif func == 'clear_copy_task': |
||||
print(clearCopyTask()) |
||||
elif func == 'home_page': |
||||
print(homePage()) |
||||
else: |
||||
print('error') |
@ -0,0 +1,17 @@ |
||||
{ |
||||
"sort": 7, |
||||
"ps": "一个支持多种存储的文件列表程序", |
||||
"name": "alist", |
||||
"title": "Alist", |
||||
"shell": "install.sh", |
||||
"versions":["3.37.4","3.38.0"], |
||||
"tip": "soft", |
||||
"checks": "server/alist", |
||||
"path": "server/alist", |
||||
"display": 1, |
||||
"author": "alist", |
||||
"date": "2022-10-09", |
||||
"home": "https://alist.nn.ci", |
||||
"type": 0, |
||||
"pid": "5" |
||||
} |
@ -0,0 +1,13 @@ |
||||
[Unit] |
||||
Description=A file list program that supports multiple storage |
||||
After=network.target |
||||
|
||||
[Service] |
||||
Type=simple |
||||
WorkingDirectory={$SERVER_PATH}/alist |
||||
ExecStart={$SERVER_PATH}/alist/alist server |
||||
ExecReload=/bin/kill -USR2 $MAINPID |
||||
Restart=on-failure |
||||
|
||||
[Install] |
||||
WantedBy=multi-user.target |
@ -0,0 +1,46 @@ |
||||
#!/bin/sh |
||||
# chkconfig: 2345 55 25 |
||||
# description: alist Service |
||||
|
||||
### BEGIN INIT INFO |
||||
# Provides: alist |
||||
# Required-Start: $all |
||||
# Required-Stop: $all |
||||
# Default-Start: 2 3 4 5 |
||||
# Default-Stop: 0 1 6 |
||||
# Short-Description: starts alist |
||||
# Description: starts the MDW-Web |
||||
### END INIT INFO |
||||
|
||||
# Simple alist init.d script conceived to work on Linux systems |
||||
# as it does use of the /proc filesystem. |
||||
|
||||
app_start(){ |
||||
echo "Starting alist server..." |
||||
cd {$SERVER_PATH}/alist |
||||
./alist server >> {$SERVER_PATH}/alist/logs.pl 2>&1 & |
||||
} |
||||
|
||||
app_stop(){ |
||||
echo "dztasks stopped" |
||||
ps -ef| grep alist | grep -v grep | grep -v python | grep -v sh | awk '{print $2}'| xargs kill |
||||
} |
||||
|
||||
|
||||
case "$1" in |
||||
start) |
||||
app_start |
||||
;; |
||||
stop) |
||||
app_stop |
||||
;; |
||||
restart|reload) |
||||
app_stop |
||||
sleep 0.3 |
||||
app_start |
||||
;; |
||||
*) |
||||
echo "Please use start or stop as first argument" |
||||
;; |
||||
esac |
||||
|
@ -0,0 +1,94 @@ |
||||
#!/bin/bash |
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin |
||||
export PATH |
||||
|
||||
curPath=`pwd` |
||||
rootPath=$(dirname "$curPath") |
||||
rootPath=$(dirname "$rootPath") |
||||
serverPath=$(dirname "$rootPath") |
||||
|
||||
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/alist && bash install.sh install 3.37.4 |
||||
# cd /www/server/mdserver-web/plugins/alist && bash install.sh install 3.37.4 |
||||
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl |
||||
VERSION=$2 |
||||
|
||||
sysArch=`arch` |
||||
sysName=`uname` |
||||
|
||||
ALIST_ARCH_NAME=amd64 |
||||
if [ "$sysArch" == "arm64" ];then |
||||
ALIST_ARCH_NAME=arm64 |
||||
elif [ "$sysArch" == "x86_64" ]; then |
||||
ALIST_ARCH_NAME=amd64 |
||||
elif [ "$sysArch" == "aarch64" ]; then |
||||
ALIST_ARCH_NAME=arm64 |
||||
fi |
||||
|
||||
ALIST_NAME=linux |
||||
if [ "$sysName" == "Darwin" ];then |
||||
ALIST_NAME=darwin |
||||
fi |
||||
|
||||
Install_App() |
||||
{ |
||||
echo '正在安装脚本文件...' |
||||
|
||||
mkdir -p $serverPath/source |
||||
mkdir -p $serverPath/source/alist |
||||
|
||||
FILE_TGZ=alist-${ALIST_NAME}-${ALIST_ARCH_NAME}.tar.gz |
||||
|
||||
ALIST_DIR=$serverPath/source/alist |
||||
|
||||
if [ ! -f $ALIST_DIR/${FILE_TGZ} ];then |
||||
wget -O $ALIST_DIR/${FILE_TGZ} https://github.com/alist-org/alist/releases/download/v${VERSION}/${FILE_TGZ} |
||||
fi |
||||
|
||||
mkdir -p $serverPath/alist |
||||
|
||||
cd $ALIST_DIR && tar -zxvf ${FILE_TGZ} -C $serverPath/alist |
||||
echo "${VERSION}" > $serverPath/alist/version.pl |
||||
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/alist/index.py start |
||||
cd ${rootPath} && python3 ${rootPath}/plugins/alist/index.py initd_install |
||||
|
||||
cd $serverPath/alist && ./alist admin set admin |
||||
# cd /www/server/alist && ./alist admin set admin |
||||
|
||||
echo '安装完成' |
||||
} |
||||
|
||||
Uninstall_App() |
||||
{ |
||||
if [ -f /usr/lib/systemd/system/alist.service ];then |
||||
systemctl stop alist |
||||
systemctl disable alist |
||||
rm -rf /usr/lib/systemd/system/alist.service |
||||
systemctl daemon-reload |
||||
fi |
||||
|
||||
if [ -f /lib/systemd/system/alist.service ];then |
||||
systemctl stop alist |
||||
systemctl disable alist |
||||
rm -rf /lib/systemd/system/alist.service |
||||
systemctl daemon-reload |
||||
fi |
||||
|
||||
if [ -f $serverPath/alist/initd/alist ];then |
||||
$serverPath/alist/initd/alist stop |
||||
fi |
||||
|
||||
if [ -d $serverPath/alist ];then |
||||
rm -rf $serverPath/alist |
||||
fi |
||||
|
||||
echo "卸载alist成功" |
||||
} |
||||
|
||||
action=$1 |
||||
if [ "${1}" == 'install' ];then |
||||
Install_App |
||||
else |
||||
Uninstall_App |
||||
fi |
@ -0,0 +1,92 @@ |
||||
function alistPost(method, version, args,callback){ |
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); |
||||
|
||||
var req_data = {}; |
||||
req_data['name'] = 'alist'; |
||||
req_data['func'] = method; |
||||
req_data['version'] = version; |
||||
|
||||
if (typeof(args) == 'string'){ |
||||
req_data['args'] = JSON.stringify(toArrayObject(args)); |
||||
} else { |
||||
req_data['args'] = JSON.stringify(args); |
||||
} |
||||
|
||||
$.post('/plugins/run', req_data, function(data) { |
||||
layer.close(loadT); |
||||
if (!data.status){ |
||||
//错误展示10S
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']}); |
||||
return; |
||||
} |
||||
|
||||
if(typeof(callback) == 'function'){ |
||||
callback(data); |
||||
} |
||||
},'json');
|
||||
} |
||||
|
||||
function alistPostCallbak(method, version, args,callback){ |
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); |
||||
|
||||
var req_data = {}; |
||||
req_data['name'] = 'alist'; |
||||
req_data['func'] = method; |
||||
args['version'] = version; |
||||
|
||||
if (typeof(args) == 'string'){ |
||||
req_data['args'] = JSON.stringify(toArrayObject(args)); |
||||
} else { |
||||
req_data['args'] = JSON.stringify(args); |
||||
} |
||||
|
||||
$.post('/plugins/callback', req_data, function(data) { |
||||
layer.close(loadT); |
||||
if (!data.status){ |
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); |
||||
return; |
||||
} |
||||
|
||||
if(typeof(callback) == 'function'){ |
||||
callback(data); |
||||
} |
||||
},'json');
|
||||
} |
||||
|
||||
function clearTaskCopy(){ |
||||
layer.confirm('您真的要清空复制任务吗?', { icon: 3, closeBtn: 2 }, function() { |
||||
alistPost('clear_copy_task', '', {}, function(data){ |
||||
var rdata = $.parseJSON(data.data); |
||||
showMsg(rdata.msg, function(){},{ icon: rdata.status ? 1 : 2 }); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
function commonHomePage(){ |
||||
alistPost('home_page', '', {}, function(data){ |
||||
var rdata = $.parseJSON(data.data); |
||||
window.open(rdata.data); |
||||
}); |
||||
} |
||||
|
||||
function alistCommonFunc(){ |
||||
var con = ''; |
||||
con += '<hr/><p class="conf_p" style="text-align:center;">\ |
||||
<button class="btn btn-default btn-sm" onclick="commonHomePage()">主页</button>\ |
||||
<button class="btn btn-default btn-sm" onclick="clearTaskCopy()">清空复制任务</button>\ |
||||
</p>'; |
||||
|
||||
$(".soft-man-con").html(con); |
||||
} |
||||
|
||||
function alistReadme(){ |
||||
|
||||
|
||||
var readme = '<ul class="help-info-text c7">'; |
||||
readme += '<li>默认admin:admin</li>'; |
||||
readme += '<li>手动改密码: cd /www/server/alist && ./alist admin set NEW_PASSWORD</li>'; |
||||
readme += '</ul>'; |
||||
|
||||
$('.soft-man-con').html(readme);
|
||||
} |
||||
|
After Width: | Height: | Size: 31 KiB |
@ -0,0 +1,31 @@ |
||||
<style> |
||||
.overflow_hide { |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
white-space: nowrap; |
||||
vertical-align: middle; |
||||
} |
||||
</style> |
||||
|
||||
<div class="bt-form"> |
||||
<div class='plugin_version'></div> |
||||
<div class="bt-w-main"> |
||||
<div class="bt-w-menu"> |
||||
<p class="bgw" onclick="pluginService('cloudreve');">服务</p> |
||||
<p onclick="pluginInitD('cloudreve');">自启动</p> |
||||
<p onclick="alistCommonFunc();">常用功能</p> |
||||
<p onclick="pluginConfigTpl('cloudreve',$('.plugin_version').attr('version'));">配置修改</p> |
||||
<p onclick="pluginLogs('cloudreve','','run_log');">运行日志</p> |
||||
<p onclick="alistReadme();">相关说明</p> |
||||
|
||||
</div> |
||||
<div class="bt-w-con pd15"> |
||||
<div class="soft-man-con" style="height: 520px; overflow: auto;"></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<script type="text/javascript"> |
||||
$.getScript( "/plugins/file?name=cloudreve&f=js/cloudreve.js", function(){ |
||||
pluginService('cloudreve', $('.plugin_version').attr('version')); |
||||
}); |
||||
</script> |
@ -0,0 +1,288 @@ |
||||
# coding:utf-8 |
||||
|
||||
import sys |
||||
import io |
||||
import os |
||||
import time |
||||
import re |
||||
|
||||
sys.path.append(os.getcwd() + "/class/core") |
||||
import mw |
||||
|
||||
app_debug = False |
||||
if mw.isAppleSystem(): |
||||
app_debug = True |
||||
|
||||
|
||||
def getPluginName(): |
||||
return 'cloudreve' |
||||
|
||||
|
||||
def getPluginDir(): |
||||
return mw.getPluginDir() + '/' + getPluginName() |
||||
|
||||
|
||||
def getServerDir(): |
||||
return mw.getServerDir() + '/' + getPluginName() |
||||
|
||||
|
||||
def getInitDFile(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return '/tmp/' + getPluginName() |
||||
|
||||
if current_os.startswith('freebsd'): |
||||
return '/etc/rc.d/' + getPluginName() |
||||
|
||||
return '/etc/init.d/' + getPluginName() |
||||
|
||||
|
||||
def getInitDTpl(): |
||||
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl" |
||||
return path |
||||
|
||||
|
||||
def getArgs(): |
||||
args = sys.argv[3:] |
||||
tmp = {} |
||||
args_len = len(args) |
||||
|
||||
if args_len == 1: |
||||
t = args[0].strip('{').strip('}') |
||||
if t.strip() == '': |
||||
tmp = [] |
||||
else: |
||||
t = t.split(':') |
||||
tmp[t[0]] = t[1] |
||||
tmp[t[0]] = t[1] |
||||
elif args_len > 1: |
||||
for i in range(len(args)): |
||||
t = args[i].split(':') |
||||
tmp[t[0]] = t[1] |
||||
return tmp |
||||
|
||||
def checkArgs(data, ck=[]): |
||||
for i in range(len(ck)): |
||||
if not ck[i] in data: |
||||
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) |
||||
return (True, mw.returnJson(True, 'ok')) |
||||
|
||||
|
||||
def getConf(): |
||||
path = getServerDir() + "/conf.ini" |
||||
return path |
||||
|
||||
def configTpl(): |
||||
path = getPluginDir() + '/tpl' |
||||
pathFile = os.listdir(path) |
||||
tmp = [] |
||||
for one in pathFile: |
||||
file = path + '/' + one |
||||
tmp.append(file) |
||||
return mw.getJson(tmp) |
||||
|
||||
|
||||
def readConfigTpl(): |
||||
args = getArgs() |
||||
data = checkArgs(args, ['file']) |
||||
if not data[0]: |
||||
return data[1] |
||||
|
||||
content = mw.readFile(args['file']) |
||||
content = contentReplace(content) |
||||
return mw.returnJson(True, 'ok', content) |
||||
|
||||
|
||||
def status(): |
||||
data = mw.execShell( |
||||
"ps aux|grep cloudreve |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'") |
||||
|
||||
if data[0] == '': |
||||
return 'stop' |
||||
return 'start' |
||||
|
||||
def contentReplace(content): |
||||
service_path = mw.getServerDir() |
||||
content = content.replace('{$ROOT_PATH}', mw.getRootDir()) |
||||
content = content.replace('{$SERVER_PATH}', service_path) |
||||
content = content.replace('{$SERVER_APP}', service_path + '/'+getPluginName()) |
||||
return content |
||||
|
||||
def initDreplace(): |
||||
|
||||
file_tpl = getInitDTpl() |
||||
service_path = os.path.dirname(os.getcwd()) |
||||
|
||||
initD_path = getServerDir() + '/init.d' |
||||
if not os.path.exists(initD_path): |
||||
os.mkdir(initD_path) |
||||
file_bin = initD_path + '/' + getPluginName() |
||||
|
||||
# initd replace |
||||
if not os.path.exists(file_bin): |
||||
content = mw.readFile(file_tpl) |
||||
content = content.replace('{$SERVER_PATH}', service_path) |
||||
mw.writeFile(file_bin, content) |
||||
mw.execShell('chmod +x ' + file_bin) |
||||
|
||||
# systemd |
||||
systemDir = mw.systemdCfgDir() |
||||
systemService = systemDir + '/' + getPluginName() + '.service' |
||||
if os.path.exists(systemDir) and not os.path.exists(systemService): |
||||
systemServiceTpl = getPluginDir() + '/init.d/' + getPluginName() + '.service.tpl' |
||||
service_path = mw.getServerDir() |
||||
se_content = mw.readFile(systemServiceTpl) |
||||
se_content = se_content.replace('{$SERVER_PATH}', service_path) |
||||
mw.writeFile(systemService, se_content) |
||||
mw.execShell('systemctl daemon-reload') |
||||
|
||||
return file_bin |
||||
|
||||
|
||||
def alistOp(method): |
||||
file = initDreplace() |
||||
|
||||
current_os = mw.getOs() |
||||
if current_os == "darwin": |
||||
data = mw.execShell(file + ' ' + method) |
||||
if data[1] == '': |
||||
return 'ok' |
||||
return data[1] |
||||
|
||||
if current_os.startswith("freebsd"): |
||||
data = mw.execShell('service ' + getPluginName() + ' ' + method) |
||||
if data[1] == '': |
||||
return 'ok' |
||||
return data[1] |
||||
|
||||
data = mw.execShell('systemctl ' + method + ' ' + getPluginName()) |
||||
if data[1] == '': |
||||
return 'ok' |
||||
return data[1] |
||||
|
||||
|
||||
def start(): |
||||
return alistOp('start') |
||||
|
||||
|
||||
def stop(): |
||||
return alistOp('stop') |
||||
|
||||
|
||||
def restart(): |
||||
status = alistOp('restart') |
||||
return status |
||||
|
||||
|
||||
def reload(): |
||||
return alistOp('reload') |
||||
|
||||
|
||||
def initdStatus(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return "Apple Computer does not support" |
||||
|
||||
if current_os.startswith('freebsd'): |
||||
initd_bin = getInitDFile() |
||||
if os.path.exists(initd_bin): |
||||
return 'ok' |
||||
|
||||
shell_cmd = 'systemctl status ' + \ |
||||
getPluginName() + ' | grep loaded | grep "enabled;"' |
||||
data = mw.execShell(shell_cmd) |
||||
if data[0] == '': |
||||
return 'fail' |
||||
return 'ok' |
||||
|
||||
|
||||
def initdInstall(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return "Apple Computer does not support" |
||||
|
||||
# freebsd initd install |
||||
if current_os.startswith('freebsd'): |
||||
import shutil |
||||
source_bin = initDreplace() |
||||
initd_bin = getInitDFile() |
||||
shutil.copyfile(source_bin, initd_bin) |
||||
mw.execShell('chmod +x ' + initd_bin) |
||||
mw.execShell('sysrc ' + getPluginName() + '_enable="YES"') |
||||
return 'ok' |
||||
|
||||
mw.execShell('systemctl enable ' + getPluginName()) |
||||
return 'ok' |
||||
|
||||
|
||||
def initdUinstall(): |
||||
current_os = mw.getOs() |
||||
if current_os == 'darwin': |
||||
return "Apple Computer does not support" |
||||
|
||||
if current_os.startswith('freebsd'): |
||||
initd_bin = getInitDFile() |
||||
os.remove(initd_bin) |
||||
mw.execShell('sysrc ' + getPluginName() + '_enable="NO"') |
||||
return 'ok' |
||||
|
||||
mw.execShell('systemctl disable ' + getPluginName()) |
||||
return 'ok' |
||||
|
||||
|
||||
def runLog(): |
||||
return getServerDir() + '/logs.pl' |
||||
|
||||
def pSqliteDb(dbname='databases'): |
||||
pos_file = getServerDir() + '/data/' |
||||
file = pos_file + '/data.db' |
||||
name = 'data' |
||||
conn = mw.M(dbname).dbPos(pos_file, name) |
||||
return conn |
||||
|
||||
def getCloudrevePort(): |
||||
file = getConf() |
||||
content = mw.readFile(file) |
||||
rep = r'Listen\s*=\s*(.*)' |
||||
tmp = re.search(rep, content) |
||||
return tmp.groups()[0].strip() |
||||
|
||||
def homePage(): |
||||
http_port = getCloudrevePort() |
||||
ip = mw.getLocalIp() |
||||
if mw.isAppleSystem(): |
||||
ip = '127.0.0.1' |
||||
url = 'http://'+ip+""+str(http_port) |
||||
# print(url) |
||||
return mw.returnJson(True, 'ok!', url) |
||||
|
||||
if __name__ == "__main__": |
||||
func = sys.argv[1] |
||||
if func == 'status': |
||||
print(status()) |
||||
elif func == 'start': |
||||
print(start()) |
||||
elif func == 'stop': |
||||
print(stop()) |
||||
elif func == 'restart': |
||||
print(restart()) |
||||
elif func == 'reload': |
||||
print(reload()) |
||||
elif func == 'initd_status': |
||||
print(initdStatus()) |
||||
elif func == 'initd_install': |
||||
print(initdInstall()) |
||||
elif func == 'initd_uninstall': |
||||
print(initdUinstall()) |
||||
elif func == 'conf': |
||||
print(getConf()) |
||||
elif func == 'run_log': |
||||
print(runLog()) |
||||
elif func == 'config_tpl': |
||||
print(configTpl()) |
||||
elif func == 'read_config_tpl': |
||||
print(readConfigTpl()) |
||||
elif func == 'home_page': |
||||
print(homePage()) |
||||
else: |
||||
print('error') |
@ -0,0 +1,17 @@ |
||||
{ |
||||
"sort": 7, |
||||
"ps": "一个支持多种存储的文件列表程序", |
||||
"name": "cloudreve", |
||||
"title": "cloudreve", |
||||
"shell": "install.sh", |
||||
"versions":["3.8.3"], |
||||
"tip": "soft", |
||||
"checks": "server/cloudreve", |
||||
"path": "server/cloudreve", |
||||
"display": 1, |
||||
"author": "cloudreve", |
||||
"date": "2024-10-14", |
||||
"home": "https://cloudreve.org/", |
||||
"type": 0, |
||||
"pid": "5" |
||||
} |
@ -0,0 +1,13 @@ |
||||
[Unit] |
||||
Description=A file list program that supports multiple storage |
||||
After=network.target |
||||
|
||||
[Service] |
||||
Type=simple |
||||
WorkingDirectory={$SERVER_PATH}/cloudreve |
||||
ExecStart={$SERVER_PATH}/cloudreve/cloudreve |
||||
ExecReload=/bin/kill -USR2 $MAINPID |
||||
Restart=on-failure |
||||
|
||||
[Install] |
||||
WantedBy=multi-user.target |
@ -0,0 +1,46 @@ |
||||
#!/bin/sh |
||||
# chkconfig: 2345 55 25 |
||||
# description: cloudreve Service |
||||
|
||||
### BEGIN INIT INFO |
||||
# Provides: cloudreve |
||||
# Required-Start: $all |
||||
# Required-Stop: $all |
||||
# Default-Start: 2 3 4 5 |
||||
# Default-Stop: 0 1 6 |
||||
# Short-Description: starts cloudreve |
||||
# Description: starts the MDW-Web |
||||
### END INIT INFO |
||||
|
||||
# Simple cloudreve init.d script conceived to work on Linux systems |
||||
# as it does use of the /proc filesystem. |
||||
|
||||
app_start(){ |
||||
echo "Starting cloudreve server..." |
||||
cd {$SERVER_PATH}/cloudreve |
||||
./cloudreve >> {$SERVER_PATH}/cloudreve/logs.pl 2>&1 & |
||||
} |
||||
|
||||
app_stop(){ |
||||
echo "dztasks stopped" |
||||
ps -ef| grep cloudreve | grep -v grep | grep -v python | grep -v sh | awk '{print $2}'| xargs kill |
||||
} |
||||
|
||||
|
||||
case "$1" in |
||||
start) |
||||
app_start |
||||
;; |
||||
stop) |
||||
app_stop |
||||
;; |
||||
restart|reload) |
||||
app_stop |
||||
sleep 0.3 |
||||
app_start |
||||
;; |
||||
*) |
||||
echo "Please use start or stop as first argument" |
||||
;; |
||||
esac |
||||
|
@ -0,0 +1,91 @@ |
||||
#!/bin/bash |
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin |
||||
export PATH |
||||
|
||||
curPath=`pwd` |
||||
rootPath=$(dirname "$curPath") |
||||
rootPath=$(dirname "$rootPath") |
||||
serverPath=$(dirname "$rootPath") |
||||
|
||||
# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/cloudreve && bash install.sh install 3.8.3 |
||||
# cd /www/server/mdserver-web/plugins/cloudreve && bash install.sh install 3.8.3 |
||||
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl |
||||
VERSION=$2 |
||||
|
||||
sysArch=`arch` |
||||
sysName=`uname` |
||||
|
||||
ALIST_ARCH_NAME=amd64 |
||||
if [ "$sysArch" == "arm64" ];then |
||||
ALIST_ARCH_NAME=arm64 |
||||
elif [ "$sysArch" == "x86_64" ]; then |
||||
ALIST_ARCH_NAME=amd64 |
||||
elif [ "$sysArch" == "aarch64" ]; then |
||||
ALIST_ARCH_NAME=aarch64 |
||||
fi |
||||
|
||||
ALIST_NAME=linux |
||||
if [ "$sysName" == "Darwin" ];then |
||||
ALIST_NAME=darwin |
||||
fi |
||||
|
||||
Install_App() |
||||
{ |
||||
echo '正在安装脚本文件...' |
||||
|
||||
mkdir -p $serverPath/source |
||||
mkdir -p $serverPath/source/cloudreve |
||||
|
||||
FILE_TGZ=cloudreve_${VERSION}_${ALIST_NAME}_${ALIST_ARCH_NAME}.tar.gz |
||||
CLOUDREVE_DIR=$serverPath/source/cloudreve |
||||
|
||||
if [ ! -f $CLOUDREVE_DIR/${FILE_TGZ} ];then |
||||
wget -O $CLOUDREVE_DIR/${FILE_TGZ} https://github.com/cloudreve/Cloudreve/releases/download/${VERSION}/${FILE_TGZ} |
||||
fi |
||||
|
||||
mkdir -p $serverPath/cloudreve |
||||
|
||||
cd $CLOUDREVE_DIR && tar -zxvf ${FILE_TGZ} -C $serverPath/cloudreve |
||||
echo "${VERSION}" > $serverPath/cloudreve/version.pl |
||||
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/cloudreve/index.py start |
||||
cd ${rootPath} && python3 ${rootPath}/plugins/cloudreve/index.py initd_install |
||||
|
||||
# cd $serverPath/cloudreve && ./alist admin set admin |
||||
echo '安装cloudreve完成' |
||||
} |
||||
|
||||
Uninstall_App() |
||||
{ |
||||
if [ -f /usr/lib/systemd/system/cloudreve.service ];then |
||||
systemctl stop cloudreve |
||||
systemctl disable cloudreve |
||||
rm -rf /usr/lib/systemd/system/cloudreve.service |
||||
systemctl daemon-reload |
||||
fi |
||||
|
||||
if [ -f /lib/systemd/system/cloudreve.service ];then |
||||
systemctl stop cloudreve |
||||
systemctl disable cloudreve |
||||
rm -rf /lib/systemd/system/cloudreve.service |
||||
systemctl daemon-reload |
||||
fi |
||||
|
||||
if [ -f $serverPath/cloudreve/initd/cloudreve ];then |
||||
$serverPath/cloudreve/initd/cloudreve stop |
||||
fi |
||||
|
||||
if [ -d $serverPath/cloudreve ];then |
||||
rm -rf $serverPath/cloudreve |
||||
fi |
||||
|
||||
echo "卸载cloudreve成功" |
||||
} |
||||
|
||||
action=$1 |
||||
if [ "${1}" == 'install' ];then |
||||
Install_App |
||||
else |
||||
Uninstall_App |
||||
fi |
@ -0,0 +1,82 @@ |
||||
function alistPost(method, version, args,callback){ |
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); |
||||
|
||||
var req_data = {}; |
||||
req_data['name'] = 'cloudreve'; |
||||
req_data['func'] = method; |
||||
req_data['version'] = version; |
||||
|
||||
if (typeof(args) == 'string'){ |
||||
req_data['args'] = JSON.stringify(toArrayObject(args)); |
||||
} else { |
||||
req_data['args'] = JSON.stringify(args); |
||||
} |
||||
|
||||
$.post('/plugins/run', req_data, function(data) { |
||||
layer.close(loadT); |
||||
if (!data.status){ |
||||
//错误展示10S
|
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']}); |
||||
return; |
||||
} |
||||
|
||||
if(typeof(callback) == 'function'){ |
||||
callback(data); |
||||
} |
||||
},'json');
|
||||
} |
||||
|
||||
function alistPostCallbak(method, version, args,callback){ |
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); |
||||
|
||||
var req_data = {}; |
||||
req_data['name'] = 'cloudreve'; |
||||
req_data['func'] = method; |
||||
args['version'] = version; |
||||
|
||||
if (typeof(args) == 'string'){ |
||||
req_data['args'] = JSON.stringify(toArrayObject(args)); |
||||
} else { |
||||
req_data['args'] = JSON.stringify(args); |
||||
} |
||||
|
||||
$.post('/plugins/callback', req_data, function(data) { |
||||
layer.close(loadT); |
||||
if (!data.status){ |
||||
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); |
||||
return; |
||||
} |
||||
|
||||
if(typeof(callback) == 'function'){ |
||||
callback(data); |
||||
} |
||||
},'json');
|
||||
} |
||||
|
||||
|
||||
function commonHomePage(){ |
||||
alistPost('home_page', '', {}, function(data){ |
||||
var rdata = $.parseJSON(data.data); |
||||
window.open(rdata.data); |
||||
}); |
||||
} |
||||
|
||||
function alistCommonFunc(){ |
||||
var con = ''; |
||||
con += '<hr/><p class="conf_p" style="text-align:center;">\ |
||||
<button class="btn btn-default btn-sm" onclick="commonHomePage()">主页</button>\ |
||||
</p>'; |
||||
|
||||
$(".soft-man-con").html(con); |
||||
} |
||||
|
||||
function alistReadme(){ |
||||
|
||||
|
||||
var readme = '<ul class="help-info-text c7">'; |
||||
readme += '<li>记住安装时生成的用户+密码</li>'; |
||||
readme += '</ul>'; |
||||
|
||||
$('.soft-man-con').html(readme);
|
||||
} |
||||
|
@ -0,0 +1,25 @@ |
||||
[DEFAULT] |
||||
allowipv6 = auto |
||||
|
||||
action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] |
||||
|
||||
action_mw = %(action_)s |
||||
%(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] |
||||
|
||||
action_mwl = %(action_)s |
||||
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"] |
||||
|
||||
action_xarf = %(action_)s |
||||
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"] |
||||
|
||||
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"] |
||||
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"] |
||||
|
||||
action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"] |
||||
|
||||
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"] |
||||
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"] |
||||
|
||||
action_abuseipdb = abuseipdb |
||||
|
||||
action = %(action_)s |
@ -0,0 +1,2 @@ |
||||
[DEFAULT] |
||||
backend = systemd |
@ -0,0 +1,11 @@ |
||||
#sshd-START |
||||
[sshd] |
||||
enabled = true |
||||
filter = sshd |
||||
port = 2022,no |
||||
maxretry = 5 |
||||
findtime = 300 |
||||
bantime = 86400 |
||||
action = %(action_mwl)s |
||||
logpath = /var/log/auth.log |
||||
#sshd-END |
@ -0,0 +1,182 @@ |
||||
#!/bin/bash |
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin |
||||
export PATH |
||||
# LANG=en_US.UTF-8 |
||||
is64bit=`getconf LONG_BIT` |
||||
|
||||
echo -e "您正在安装的是\033[31mmdserver-web测试版\033[0m,非开发测试用途请使用正式版 install.sh !" |
||||
echo -e "You are installing\033[31m mdserver-web dev version\033[0m, normally use install.sh for production.\n" |
||||
sleep 1 |
||||
|
||||
LOG_FILE=/var/log/mw-install.log |
||||
|
||||
{ |
||||
|
||||
if [ -f /etc/motd ];then |
||||
echo "welcome to mdserver-web panel" > /etc/motd |
||||
fi |
||||
|
||||
startTime=`date +%s` |
||||
|
||||
_os=`uname` |
||||
echo "use system: ${_os}" |
||||
|
||||
|
||||
if [ ${_os} == "Darwin" ]; then |
||||
OSNAME='macos' |
||||
elif grep -Eq "openSUSE" /etc/*-release; then |
||||
OSNAME='opensuse' |
||||
zypper refresh |
||||
zypper install -y wget curl zip unzip unrar rar |
||||
elif grep -Eq "FreeBSD" /etc/*-release; then |
||||
OSNAME='freebsd' |
||||
pkg install -y wget curl zip unzip unrar rar |
||||
elif grep -Eqi "EulerOS" /etc/*-release || grep -Eqi "openEuler" /etc/*-release; then |
||||
OSNAME='euler' |
||||
yum install -y wget curl zip unzip tar crontabs |
||||
elif grep -Eqi "CentOS" /etc/issue || grep -Eqi "CentOS" /etc/*-release; then |
||||
OSNAME='rhel' |
||||
yum install -y wget zip unzip tar |
||||
elif grep -Eqi "Fedora" /etc/issue || grep -Eqi "Fedora" /etc/*-release; then |
||||
OSNAME='rhel' |
||||
yum install -y wget zip unzip tar |
||||
elif grep -Eqi "Rocky" /etc/issue || grep -Eqi "Rocky" /etc/*-release; then |
||||
OSNAME='rhel' |
||||
yum install -y wget zip unzip |
||||
elif grep -Eqi "AlmaLinux" /etc/issue || grep -Eqi "AlmaLinux" /etc/*-release; then |
||||
OSNAME='rhel' |
||||
yum install -y wget zip unzip tar |
||||
elif grep -Eqi "Amazon Linux" /etc/issue || grep -Eqi "Amazon Linux" /etc/*-release; then |
||||
OSNAME='amazon' |
||||
yum install -y wget zip unzip tar |
||||
elif grep -Eqi "Ubuntu" /etc/issue || grep -Eqi "Ubuntu" /etc/*-release; then |
||||
OSNAME='ubuntu' |
||||
apt install -y wget zip unzip tar |
||||
elif grep -Eqi "Debian" /etc/issue || grep -Eqi "Debian" /etc/*-release; then |
||||
OSNAME='debian' |
||||
apt update -y |
||||
apt install -y devscripts |
||||
apt install -y wget zip unzip tar |
||||
else |
||||
OSNAME='unknow' |
||||
fi |
||||
|
||||
if [ "$EUID" -ne 0 ] && [ "$OSNAME" != "macos" ];then |
||||
echo "Please run as root!" |
||||
exit |
||||
fi |
||||
|
||||
# HTTP_PREFIX="https://" |
||||
# LOCAL_ADDR=common |
||||
# ping -c 1 github.com > /dev/null 2>&1 |
||||
# if [ "$?" != "0" ];then |
||||
# LOCAL_ADDR=cn |
||||
# HTTP_PREFIX="https://mirror.ghproxy.com/" |
||||
# fi |
||||
|
||||
HTTP_PREFIX="https://" |
||||
LOCAL_ADDR=common |
||||
cn=$(curl -fsSL -m 10 -s http://ipinfo.io/json | grep "\"country\": \"CN\"") |
||||
if [ ! -z "$cn" ] || [ "$?" == "0" ] ;then |
||||
LOCAL_ADDR=cn |
||||
HTTP_PREFIX="https://mirror.ghproxy.com/" |
||||
fi |
||||
|
||||
echo "local:${LOCAL_ADDR}" |
||||
echo "OSNAME:${OSNAME}" |
||||
|
||||
if [ $OSNAME != "macos" ];then |
||||
|
||||
if id www &> /dev/null ;then |
||||
echo "" |
||||
else |
||||
groupadd www |
||||
useradd -g www -s /usr/sbin/nologin www |
||||
fi |
||||
|
||||
mkdir -p /www/server |
||||
mkdir -p /www/wwwroot |
||||
mkdir -p /www/wwwlogs |
||||
mkdir -p /www/backup/database |
||||
mkdir -p /www/backup/site |
||||
|
||||
if [ ! -d /www/server/mdserver-web ];then |
||||
|
||||
if [ "$LOCAL_ADDR" == "common" ];then |
||||
curl --insecure -sSLo /tmp/dev.zip ${HTTP_PREFIX}github.com/midoks/mdserver-web/archive/refs/heads/dev.zip |
||||
cd /tmp && unzip /tmp/dev.zip |
||||
mv -f /tmp/mdserver-web-dev /www/server/mdserver-web |
||||
rm -rf /tmp/dev.zip |
||||
rm -rf /tmp/mdserver-web-dev |
||||
else |
||||
# curl --insecure -sSLo /tmp/dev.zip https://code.midoks.icu/midoks/mdserver-web/archive/dev.zip |
||||
wget --no-check-certificate -O /tmp/dev.zip https://code.midoks.icu/midoks/mdserver-web/archive/dev.zip |
||||
cd /tmp && unzip /tmp/dev.zip |
||||
mv -f /tmp/mdserver-web /www/server/mdserver-web |
||||
rm -rf /tmp/dev.zip |
||||
rm -rf /tmp/mdserver-web |
||||
fi |
||||
fi |
||||
|
||||
# install acme.sh |
||||
if [ ! -d /root/.acme.sh ];then |
||||
if [ "$LOCAL_ADDR" != "common" ];then |
||||
# curl -sSL -o /tmp/acme.tar.gz ${HTTP_PREFIX}github.com/acmesh-official/acme.sh/archive/master.tar.gz |
||||
curl --insecure -sSLo /tmp/acme.tar.gz https://gitee.com/neilpang/acme.sh/repository/archive/master.tar.gz |
||||
tar xvzf /tmp/acme.tar.gz -C /tmp |
||||
cd /tmp/acme.sh-master |
||||
bash acme.sh install |
||||
fi |
||||
|
||||
if [ ! -d /root/.acme.sh ];then |
||||
curl https://get.acme.sh | sh |
||||
fi |
||||
fi |
||||
fi |
||||
|
||||
echo "use system version: ${OSNAME}" |
||||
|
||||
if [ "${OSNAME}" == "macos" ];then |
||||
curl --insecure -fsSL https://code.midoks.icu/midoks/mdserver-web/raw/branch/master/scripts/install/macos.sh | bash |
||||
else |
||||
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh |
||||
fi |
||||
|
||||
if [ "${OSNAME}" == "macos" ];then |
||||
echo "macos end" |
||||
exit 0 |
||||
fi |
||||
|
||||
cd /www/server/mdserver-web && bash cli_new.sh start |
||||
isStart=`ps -ef|grep 'gunicorn -c setting.py app:app' |grep -v grep|awk '{print $2}'` |
||||
n=0 |
||||
while [ ! -f /etc/rc.d/init.d/mw ]; |
||||
do |
||||
echo -e ".\c" |
||||
sleep 1 |
||||
let n+=1 |
||||
if [ $n -gt 20 ];then |
||||
echo -e "start mw fail" |
||||
exit 1 |
||||
fi |
||||
done |
||||
|
||||
cd /www/server/mdserver-web && bash /etc/rc.d/init.d/mw stop |
||||
cd /www/server/mdserver-web && bash /etc/rc.d/init.d/mw start |
||||
cd /www/server/mdserver-web && bash /etc/rc.d/init.d/mw default |
||||
|
||||
sleep 2 |
||||
if [ ! -e /usr/bin/mw ]; then |
||||
if [ -f /etc/rc.d/init.d/mw ];then |
||||
ln -s /etc/rc.d/init.d/mw /usr/bin/mw |
||||
fi |
||||
fi |
||||
|
||||
endTime=`date +%s` |
||||
((outTime=(${endTime}-${startTime})/60)) |
||||
echo -e "Time consumed:\033[32m $outTime \033[0mMinute!" |
||||
|
||||
} 1> >(tee $LOG_FILE) 2>&1 |
||||
|
||||
echo -e "\nInstall completed. If error occurs, please contact us with the log file mw-install.log ." |
||||
echo "安装完毕,如果出现错误,请带上同目录下的安装日志 mw-install.log 联系我们反馈." |
@ -1,4 +1,6 @@ |
||||
urllib3==1.21.1 |
||||
gevent==22.10.2 |
||||
gunicorn==21.2.0 |
||||
pyyaml |
||||
sqlalchemy==1.4.47 |
||||
flask-sqlalchemy==2.5.1 |
||||
pyyaml |
||||
|
@ -0,0 +1,236 @@ |
||||
# coding:utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
import os |
||||
import sys |
||||
import json |
||||
import time |
||||
import uuid |
||||
import logging |
||||
from datetime import timedelta |
||||
|
||||
from flask import Flask |
||||
|
||||
from flask_socketio import SocketIO, emit, send |
||||
from flask import Flask, abort, current_app, session, url_for |
||||
from flask import Blueprint, render_template |
||||
from flask import render_template_string |
||||
|
||||
from flask import request |
||||
from flask import Response |
||||
|
||||
|
||||
from flask_migrate import Migrate |
||||
from flask_caching import Cache |
||||
from werkzeug.local import LocalProxy |
||||
|
||||
from admin import model |
||||
from admin import setup |
||||
|
||||
from admin.model import db as sys_db |
||||
|
||||
|
||||
import core.mw as mw |
||||
import config |
||||
import utils.config as utils_config |
||||
|
||||
root_dir = mw.getRunDir() |
||||
|
||||
socketio = SocketIO(manage_session=False, async_mode='threading', |
||||
logger=False, engineio_logger=False, debug=False, |
||||
ping_interval=25, ping_timeout=120) |
||||
|
||||
|
||||
app = Flask(__name__, template_folder='templates/default') |
||||
|
||||
# 缓存配置 |
||||
cache = Cache(config={'CACHE_TYPE': 'simple'}) |
||||
cache.init_app(app, config={'CACHE_TYPE': 'simple'}) |
||||
|
||||
# 静态文件配置 |
||||
from whitenoise import WhiteNoise |
||||
app.wsgi_app = WhiteNoise(app.wsgi_app, root="../web/static/", prefix="static/", max_age=604800) |
||||
|
||||
# session配置 |
||||
app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:] |
||||
# app.config['sessions'] = dict() |
||||
app.config['SESSION_PERMANENT'] = True |
||||
app.config['SESSION_USE_SIGNER'] = True |
||||
app.config['SESSION_KEY_PREFIX'] = 'MW_:' |
||||
app.config['SESSION_COOKIE_NAME'] = "MW_VER_1" |
||||
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=31) |
||||
|
||||
# db的配置 |
||||
app.config['SQLALCHEMY_DATABASE_URI'] = mw.getSqitePrefix()+config.SQLITE_PATH+"?timeout=20" # 使用 SQLite 数据库 |
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True |
||||
|
||||
# 初始化db |
||||
sys_db.init_app(app) |
||||
Migrate(app, sys_db) |
||||
|
||||
|
||||
# 检查数据库是否存在。如果没有就创建它。 |
||||
setup_db_required = False |
||||
if not os.path.isfile(config.SQLITE_PATH): |
||||
setup_db_required = True |
||||
|
||||
# with app.app_context(): |
||||
# sys_db.create_all() |
||||
|
||||
with app.app_context(): |
||||
if setup_db_required: |
||||
sys_db.create_all() |
||||
|
||||
# 初始化用户信息 |
||||
with app.app_context(): |
||||
if setup_db_required: |
||||
setup.init_admin_user() |
||||
setup.init_option() |
||||
|
||||
app.config['BASIC_AUTH_OPEN'] = False |
||||
with app.app_context(): |
||||
basic_auth = model.getOptionByJson('basic_auth', default={'open':False}) |
||||
if basic_auth['open']: |
||||
app.config['BASIC_AUTH_OPEN'] = True |
||||
|
||||
|
||||
# 加载模块 |
||||
from .submodules import get_submodules |
||||
for module in get_submodules(): |
||||
app.logger.info('Registering blueprint module: %s' % module) |
||||
if app.blueprints.get(module.name) is None: |
||||
app.register_blueprint(module) |
||||
|
||||
def sendAuthenticated(): |
||||
# 发送http认证信息 |
||||
request_host = mw.getHostAddr() |
||||
result = Response('', 401, {'WWW-Authenticate': 'Basic realm="%s"' % request_host.strip()}) |
||||
if not 'login' in session and not 'admin_auth' in session: |
||||
session.clear() |
||||
return result |
||||
|
||||
@app.before_request |
||||
def requestCheck(): |
||||
# 自定义basic auth认证 |
||||
if app.config['BASIC_AUTH_OPEN']: |
||||
basic_auth = model.getOptionByJson('basic_auth', default={'open':False}) |
||||
if not basic_auth['open']: |
||||
return |
||||
|
||||
auth = request.authorization |
||||
if request.path in ['/download', '/hook', '/down']: |
||||
return |
||||
if not auth: |
||||
return sendAuthenticated() |
||||
|
||||
# print(auth.username.strip(),auth.password.strip()) |
||||
salt = basic_auth['salt'] |
||||
basic_user = mw.md5(auth.username.strip() + salt) |
||||
basic_pwd = mw.md5(auth.password.strip() + salt) |
||||
if basic_user != basic_auth['basic_user'] or basic_pwd != basic_auth['basic_pwd']: |
||||
return sendAuthenticated() |
||||
|
||||
|
||||
|
||||
@app.after_request |
||||
def requestAfter(response): |
||||
response.headers['soft'] = config.APP_NAME |
||||
response.headers['mw-version'] = config.APP_VERSION |
||||
return response |
||||
|
||||
|
||||
@app.errorhandler(404) |
||||
def page_unauthorized(error): |
||||
return render_template_string('404 not found', error_info=error), 404 |
||||
|
||||
|
||||
# 设置模板全局变量 |
||||
@app.context_processor |
||||
def inject_global_variables(): |
||||
ver = config.APP_VERSION; |
||||
if mw.isDebugMode(): |
||||
ver = ver + str(time.time()) |
||||
|
||||
data = utils_config.getGlobalVar() |
||||
g_config = { |
||||
'version': ver, |
||||
'title' : 'MW面板', |
||||
'ip' : '127.0.0.1' |
||||
} |
||||
return dict(config=g_config, data=data) |
||||
|
||||
|
||||
# from flasgger import Swagger |
||||
# api = Api(app, version='1.0', title='API', description='API 文档') |
||||
# Swagger(app) |
||||
|
||||
# @app.route('/colors/<palette>/') |
||||
# def colors(palette): |
||||
# """ |
||||
# 根据调色板名称返回颜色列表 |
||||
# --- |
||||
# parameters: |
||||
# - name: palette |
||||
# in: path |
||||
# type: string |
||||
# enum: ['all', 'rgb', 'cmyk'] |
||||
# required: true |
||||
# default: all |
||||
# definitions: |
||||
# Palette: |
||||
# type: object |
||||
# properties: |
||||
# palette_name: |
||||
# type: array |
||||
# items: |
||||
# $ref: '#/definitions/Color' |
||||
# Color: |
||||
# type: string |
||||
# responses: |
||||
# 200: |
||||
# description: 返回的颜色列表,可按调色板过滤 |
||||
# schema: |
||||
# $ref: '#/definitions/Palette' |
||||
# examples: |
||||
# rgb: ['red', 'green', 'blue'] |
||||
# """ |
||||
# all_colors = { |
||||
# 'cmyk': ['cyan', 'magenta', 'yellow', 'black'], |
||||
# 'rgb': ['red', 'green', 'blue'] |
||||
# } |
||||
# if palette == 'all': |
||||
# result = all_colorselse |
||||
# result = {palette: all_colors.get(palette)} |
||||
# return jsonify(result) |
||||
|
||||
|
||||
|
||||
|
||||
# Log the startup |
||||
app.logger.info('########################################################') |
||||
app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION) |
||||
app.logger.info('########################################################') |
||||
app.logger.debug("Python syspath: %s", sys.path) |
||||
|
||||
|
||||
|
||||
# OK |
||||
socketio.init_app(app, cors_allowed_origins="*") |
||||
|
||||
# def create_app(app_name = None): |
||||
# |
||||
# if not app_name: |
||||
# app_name = config.APP_NAME |
||||
|
||||
# # Check if app is created for CLI operations or Web |
||||
# cli_mode = False |
||||
# if app_name.endswith('-cli'): |
||||
# cli_mode = True |
||||
# return app |
@ -0,0 +1,37 @@ |
||||
# coding:utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
import time |
||||
|
||||
from admin import model |
||||
from admin import session |
||||
|
||||
def isLogined(): |
||||
if 'login' in session and session['login'] == True and 'username' in session: |
||||
username = session['username'] |
||||
info = model.getUserByName(username) |
||||
if info is None: |
||||
return False |
||||
|
||||
# print(userInfo) |
||||
if info['name'] != session['username']: |
||||
return False |
||||
|
||||
now_time = int(time.time()) |
||||
|
||||
if 'overdue' in session and now_time > session['overdue']: |
||||
# 自动续期 |
||||
session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60 |
||||
return False |
||||
|
||||
if 'tmp_login_expire' in session and now_time > int(session['tmp_login_expire']): |
||||
session.clear() |
||||
return False |
||||
return True |
@ -0,0 +1,34 @@ |
||||
# coding:utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
|
||||
from flask import Blueprint, render_template |
||||
from flask import request |
||||
|
||||
from admin.user_login_check import panel_login_required |
||||
from admin.model import Crontab |
||||
|
||||
blueprint = Blueprint('crontab', __name__, url_prefix='/crontab', template_folder='../../templates/default') |
||||
@blueprint.route('/index', endpoint='index') |
||||
def index(): |
||||
return render_template('crontab.html') |
||||
|
||||
# 插件列表 |
||||
@blueprint.route('/list', endpoint='list', methods=['GET','POST']) |
||||
@panel_login_required |
||||
def list(): |
||||
page = request.args.get('p', 1) |
||||
size = 10 |
||||
count = Crontab.query.count() |
||||
print(count) |
||||
clist = Crontab.query.paginate(page=int(page), per_page=size) |
||||
print(clist) |
||||
|
||||
return [] |
@ -0,0 +1,240 @@ |
||||
# coding:utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
import io |
||||
import time |
||||
|
||||
from flask import Blueprint, render_template |
||||
from flask import make_response |
||||
from flask import redirect |
||||
from flask import Response |
||||
from flask import request,g |
||||
|
||||
from admin.common import isLogined |
||||
from admin.user_login_check import panel_login_required |
||||
from admin import cache,session |
||||
from admin import model |
||||
from admin.model import db,TempLogin,Users |
||||
|
||||
import core.mw as mw |
||||
|
||||
|
||||
blueprint = Blueprint('dashboard', __name__, url_prefix='/', template_folder='../../templates') |
||||
@blueprint.route('/') |
||||
@panel_login_required |
||||
def index(): |
||||
return render_template('default/index.html') |
||||
|
||||
# 仅针对webhook插件 |
||||
@blueprint.route("/hook", methods=['POST', 'GET']) |
||||
def webhook(): |
||||
# 兼容获取关键数据 |
||||
access_key = request.args.get('access_key', '').strip() |
||||
if access_key == '': |
||||
access_key = request.form.get('access_key', '').strip() |
||||
|
||||
params = request.args.get('params', '').strip() |
||||
if params == '': |
||||
params = request.form.get('params', '').strip() |
||||
|
||||
input_args = { |
||||
'access_key': access_key, |
||||
'params': params, |
||||
} |
||||
|
||||
wh_install_path = mw.getServerDir() + '/webhook' |
||||
if not os.path.exists(wh_install_path): |
||||
return mw.returnJson(False, '请先安装WebHook插件!') |
||||
|
||||
package = mw.getPanelDir() + "/plugins/webhook" |
||||
if not package in sys.path: |
||||
sys.path.append(package) |
||||
|
||||
try: |
||||
import webhook_index |
||||
return webhook_index.runShellArgs(input_args) |
||||
except Exception as e: |
||||
return str(e) |
||||
|
||||
# 安全路径 |
||||
@blueprint.route('/<path>',endpoint='admin_safe_path',methods=['GET']) |
||||
def admin_safe_path(path): |
||||
db_path = model.getOption('admin_path') |
||||
if db_path == path: |
||||
return render_template('default/login.html') |
||||
|
||||
unauthorized_status = model.getOption('unauthorized_status') |
||||
if unauthorized_status == '0': |
||||
return render_template('default/path.html') |
||||
return Response(status=int(unauthorized_status)) |
||||
|
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# 定义登录入口相关方法 |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
def getErrorNum(key, limit=None): |
||||
key = mw.md5(key) |
||||
num = cache.get(key) |
||||
if not num: |
||||
num = 0 |
||||
if not limit: |
||||
return num |
||||
if limit > num: |
||||
return True |
||||
return False |
||||
|
||||
|
||||
def setErrorNum(key, empty=False, expire=3600): |
||||
key = mw.md5(key) |
||||
num = cache.get(key) |
||||
if not num: |
||||
num = 0 |
||||
else: |
||||
if empty: |
||||
cache.delete(key) |
||||
return True |
||||
cache.set(key, num + 1, expire) |
||||
return True |
||||
|
||||
def login_temp_user(token): |
||||
if len(token) != 32: |
||||
return '错误的参数!' |
||||
|
||||
skey = mw.getClientIp() + '_temp_login' |
||||
if not getErrorNum(skey, 10): |
||||
return '连续10次验证失败,禁止1小时' |
||||
|
||||
stime = int(time.time()) |
||||
|
||||
tmp_data = model.getTempLoginByToken(token) |
||||
if not tmp_data: |
||||
setErrorNum(skey) |
||||
return '验证失败!' |
||||
|
||||
if stime > int(tmp_data['expire']): |
||||
setErrorNum(skey) |
||||
return "过期" |
||||
|
||||
user_data = model.getUserById(1) |
||||
|
||||
login_addr = mw.getClientIp() + ":" + str(request.environ.get('REMOTE_PORT')) |
||||
mw.writeLog('用户临时登录', "登录成功,帐号:{1},登录IP:{2}",(user_data['name'], login_addr)) |
||||
|
||||
TempLogin.query.filter(TempLogin.id==tmp_data['id']).update({"login_time": stime, 'state': 1, 'login_addr': login_addr}) |
||||
db.session.commit() |
||||
|
||||
session['login'] = True |
||||
session['username'] = user_data['name'] |
||||
session['tmp_login'] = True |
||||
session['tmp_login_id'] = str(tmp_data['id']) |
||||
session['tmp_login_expire'] = int(tmp_data['expire']) |
||||
session['uid'] = user_data['id'] |
||||
|
||||
return redirect('/') |
||||
|
||||
# 登录页: 当设置了安全路径,本页失效。 |
||||
@blueprint.route('/login') |
||||
def login(): |
||||
|
||||
# 临时登录功能 |
||||
token = request.args.get('tmp_token', '').strip() |
||||
if token != '': |
||||
return login_temp_user(token) |
||||
|
||||
# 注销登录 |
||||
signout = request.args.get('signout', '') |
||||
if signout == 'True': |
||||
session.clear() |
||||
session['login'] = False |
||||
session['overdue'] = 0 |
||||
|
||||
db_path = model.getOption('admin_path') |
||||
if db_path == '': |
||||
return render_template('default/login.html') |
||||
else: |
||||
unauthorized_status = model.getOption('unauthorized_status') |
||||
if unauthorized_status == '0': |
||||
return render_template('default/path.html') |
||||
return Response(status=int(unauthorized_status)) |
||||
|
||||
# 验证码 |
||||
@blueprint.route('/code') |
||||
def code(): |
||||
import utils.vilidate as vilidate |
||||
vie = vilidate.vieCode() |
||||
codeImage = vie.GetCodeImage(80, 4) |
||||
out = io.BytesIO() |
||||
codeImage[0].save(out, "png") |
||||
session['code'] = mw.md5(''.join(codeImage[1]).lower()) |
||||
|
||||
img = Response(out.getvalue(), headers={'Content-Type': 'image/png'}) |
||||
return make_response(img) |
||||
|
||||
# 检查是否登录 |
||||
@blueprint.route('/check_login',methods=['GET','POST']) |
||||
def check_login(): |
||||
if isLogined(): |
||||
return mw.returnData(True,'已登录') |
||||
return mw.returnData(False,'未登录') |
||||
|
||||
# 执行登录操作 |
||||
@blueprint.route('/do_login', endpoint='do_login', methods=['POST']) |
||||
def do_login(): |
||||
username = request.form.get('username', '').strip() |
||||
password = request.form.get('password', '').strip() |
||||
code = request.form.get('code', '').strip() |
||||
|
||||
login_cache_count = 5 |
||||
login_cache_limit = cache.get('login_cache_limit') |
||||
|
||||
if 'code' in session: |
||||
if session['code'] != mw.md5(code): |
||||
if login_cache_limit == None: |
||||
login_cache_limit = 1 |
||||
else: |
||||
login_cache_limit = int(login_cache_limit) + 1 |
||||
|
||||
if login_cache_limit >= login_cache_count: |
||||
model.setOption('admin_close', 'yes') |
||||
return mw.returnJson(False, '面板已经关闭!') |
||||
|
||||
cache.set('login_cache_limit', login_cache_limit, timeout=10000) |
||||
login_cache_limit = cache.get('login_cache_limit') |
||||
login_err_msg = mw.getInfo("验证码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit))) |
||||
mw.writeLog('用户登录', login_err_msg) |
||||
return mw.returnData(False, login_err_msg) |
||||
|
||||
info = model.getUserByName(username) |
||||
password = mw.md5(password) |
||||
|
||||
if info['name'] != username or info['password'] != password: |
||||
msg = "<a style='color: red'>密码错误</a>,帐号:{1},密码:{2},登录IP:{3}", (('****', '******', request.remote_addr)) |
||||
|
||||
if login_cache_limit == None: |
||||
login_cache_limit = 1 |
||||
else: |
||||
login_cache_limit = int(login_cache_limit) + 1 |
||||
|
||||
if login_cache_limit >= login_cache_count: |
||||
model.setOption('admin_close', 'yes') |
||||
return mw.returnData(False, '面板已经关闭!') |
||||
|
||||
cache.set('login_cache_limit', login_cache_limit, timeout=10000) |
||||
login_cache_limit = cache.get('login_cache_limit') |
||||
mw.writeLog('用户登录', mw.getInfo(msg)) |
||||
return mw.returnData(-1, mw.getInfo("用户名或密码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit)))) |
||||
|
||||
|
||||
session['login'] = True |
||||
session['username'] = info['name'] |
||||
session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60 |
||||
|
||||
return mw.returnJson(1, '登录成功,正在跳转...') |
@ -0,0 +1,156 @@ |
||||
# coding:utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
import os |
||||
|
||||
from flask import Blueprint, render_template |
||||
from flask import request |
||||
|
||||
|
||||
from admin import model |
||||
from admin.user_login_check import panel_login_required |
||||
import core.mw as mw |
||||
import utils.file as file |
||||
|
||||
blueprint = Blueprint('files', __name__, url_prefix='/files', template_folder='../../templates/default') |
||||
@blueprint.route('/index', endpoint='index') |
||||
@panel_login_required |
||||
def index(): |
||||
return render_template('files.html') |
||||
|
||||
# 获取文件内容 |
||||
@blueprint.route('/get_body', endpoint='get_file_body', methods=['POST']) |
||||
@panel_login_required |
||||
def get_file_body(): |
||||
path = request.form.get('path', '') |
||||
return file.getFileBody(path) |
||||
|
||||
# 获取文件内容 |
||||
@blueprint.route('/save_body', endpoint='save_body', methods=['POST']) |
||||
@panel_login_required |
||||
def save_body(): |
||||
path = request.form.get('path', '') |
||||
data = request.form.get('data', '') |
||||
encoding = request.form.get('encoding', '') |
||||
if not os.path.exists(path): |
||||
return mw.returnData(False, '文件不存在') |
||||
try: |
||||
if encoding == 'ascii': |
||||
encoding = 'utf-8' |
||||
|
||||
data = data.encode(encoding, errors='ignore').decode(encoding) |
||||
fp = open(path, 'w+', encoding=encoding) |
||||
fp.write(data) |
||||
fp.close() |
||||
|
||||
if path.find("web_conf") > 0: |
||||
mw.restartWeb() |
||||
mw.writeLog('文件管理', '文件[{1}]保存成功', (path,)) |
||||
return mw.returnData(True, '文件保存成功') |
||||
except Exception as ex: |
||||
return mw.returnData(False, '文件保存错误:' + str(ex)) |
||||
|
||||
# 获取文件内容(最新行数) |
||||
@blueprint.route('/get_last_body', endpoint='get_file_last_body', methods=['POST']) |
||||
@panel_login_required |
||||
def get_file_last_body(): |
||||
path = request.form.get('path', '') |
||||
line = request.form.get('line', '100') |
||||
|
||||
if not os.path.exists(path): |
||||
return mw.returnData(False, '文件不存在', (path,)) |
||||
|
||||
try: |
||||
data = mw.getLastLine(path, int(line)) |
||||
return mw.returnData(True, 'OK', data) |
||||
except Exception as ex: |
||||
return mw.returnData(False, '无法正确读取文件!' + str(ex)) |
||||
|
||||
|
||||
# 获取文件列表 |
||||
@blueprint.route('/get_dir', endpoint='get_dir', methods=['POST']) |
||||
@panel_login_required |
||||
def get_dir(): |
||||
path = request.form.get('path', '') |
||||
if not os.path.exists(path): |
||||
path = mw.getFatherDir() + '/wwwroot' |
||||
search = request.args.get('search', '').strip().lower() |
||||
search_all = request.args.get('all', '').strip().lower() |
||||
page = request.args.get('p', '1').strip().lower() |
||||
row = request.args.get('row', '10') |
||||
order = request.form.get('order', '') |
||||
|
||||
if search_all == 'yes' and search != '': |
||||
dir_list = file.getAllDirList(path, int(page), int(row),order, search) |
||||
else: |
||||
dir_list = file.getDirList(path, int(page), int(row),order, search) |
||||
|
||||
dir_list['page'] = mw.getPage({'p':page, 'row': row, 'tojs':'getFiles', 'count': dir_list['count']}, '1,2,3,4,5,6,7,8') |
||||
return dir_list |
||||
|
||||
# 获取站点日志目录 |
||||
@blueprint.route('/get_dir_size', endpoint='get_dir_size', methods=['POST']) |
||||
@panel_login_required |
||||
def get_dir_size(): |
||||
path = request.form.get('path', '') |
||||
size = file.getDirSize(path) |
||||
return mw.returnData(True, mw.toSize(size)) |
||||
|
||||
|
||||
# 删除文件 |
||||
@blueprint.route('/delete', endpoint='delete', methods=['POST']) |
||||
@panel_login_required |
||||
def delete(): |
||||
path = request.form.get('path', '') |
||||
return file.fileDelete(path) |
||||
|
||||
|
||||
# 删除文件 |
||||
@blueprint.route('/delete_dir', endpoint='delete_dir', methods=['POST']) |
||||
@panel_login_required |
||||
def delete_dir(): |
||||
path = request.form.get('path', '') |
||||
return file.dirDelete(path) |
||||
|
||||
|
||||
# 回收站文件 |
||||
@blueprint.route('/get_recycle_bin', endpoint='get_recycle_bin', methods=['POST']) |
||||
@panel_login_required |
||||
def get_recycle_bin(): |
||||
return file.getRecycleBin() |
||||
|
||||
# 回收站文件恢复 |
||||
@blueprint.route('/re_recycle_bin', endpoint='re_recycle_bin', methods=['POST']) |
||||
@panel_login_required |
||||
def re_recycle_bin(): |
||||
path = request.form.get('path', '') |
||||
return file.reRecycleBin(path) |
||||
|
||||
# 回收站文件 |
||||
@blueprint.route('/recycle_bin', endpoint='recycle_bin', methods=['POST']) |
||||
@panel_login_required |
||||
def recycle_bin(): |
||||
return file.toggleRecycleBin() |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,84 @@ |
||||
# coding:utf-8 |
||||
|
||||
# --------------------------------------------------------------------------------- |
||||
# MW-Linux面板 |
||||
# --------------------------------------------------------------------------------- |
||||
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. |
||||
# --------------------------------------------------------------------------------- |
||||
# Author: midoks <midoks@163.com> |
||||
# --------------------------------------------------------------------------------- |
||||
|
||||
|
||||
from flask import Blueprint, render_template |
||||
from flask import request |
||||
|
||||
from admin.user_login_check import panel_login_required |
||||
from admin.model import db, Firewall |
||||
|
||||
|
||||
from utils.firewall import Firewall as MwFirewall |
||||
|
||||
import core.mw as mw |
||||
|
||||
blueprint = Blueprint('firewall', __name__, url_prefix='/firewall', template_folder='../../templates/default') |
||||
@blueprint.route('/index', endpoint='index') |
||||
@panel_login_required |
||||
def index(): |
||||
return render_template('firewall.html') |
||||
|
||||
|
||||
# 防火墙列表 |
||||
@blueprint.route('/get_list', endpoint='get_list', methods=['POST']) |
||||
@panel_login_required |
||||
def get_list(): |
||||
p = request.form.get('p', '1').strip() |
||||
limit = request.form.get('limit', '10').strip() |
||||
|
||||
count = Firewall.query.filter_by().count() |
||||
pagination = Firewall.query.filter_by().paginate(page=int(p), per_page=int(limit)) |
||||
|
||||
rows = [] |
||||
for item in pagination.items: |
||||
t = {} |
||||
t['id'] = item.id |
||||
t['port'] = item.port |
||||
t['protocol'] = item.protocol |
||||
t['ps'] = item.ps |
||||
t['add_time'] = item.add_time |
||||
t['update_time'] = item.update_time |
||||
rows.append(t) |
||||
|
||||
data = {} |
||||
data['data'] = rows |
||||
data['page'] = mw.getPage({'count':count,'tojs':'getLogs','p':p,'row':limit}) |
||||
return data |
||||
|
||||
# 获取站点日志目录 |
||||
@blueprint.route('/get_www_path', endpoint='get_www_path', methods=['POST']) |
||||
@panel_login_required |
||||
def get_www_path(): |
||||
path = mw.getLogsDir() |
||||
return {'path': path} |
||||
|
||||
# 获取ssh信息 |
||||
@blueprint.route('/get_ssh_info', endpoint='get_ssh_info', methods=['POST']) |
||||
@panel_login_required |
||||
def get_ssh_info(): |
||||
mf = MwFirewall.instance() |
||||
return mf.getSshInfo() |
||||
|
||||
|
||||
# 切换ping开关 |
||||
@blueprint.route('/set_ping', endpoint='set_ping', methods=['POST']) |
||||
@panel_login_required |
||||
def set_ping(): |
||||
mf = MwFirewall.instance() |
||||
return mf.setPing() |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue