Merge pull request #209 from midoks/dev

0.9.13
pull/242/head 0.9.13
Mr Chen 3 years ago committed by GitHub
commit c4a844cadb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      README.md
  2. 2
      class/core/config_api.py
  3. 1
      plugins/clean/index.py
  4. 2
      plugins/clean/install.sh
  5. 6
      plugins/clean/tool_task.py
  6. 6
      plugins/mariadb/js/mariadb.js
  7. 29
      plugins/mysql/js/mysql.js
  8. 4
      plugins/mysql/versions/5.7/install.sh
  9. 4
      plugins/op_waf/conf/luawaf.conf
  10. 2
      plugins/op_waf/index.html
  11. 44
      plugins/op_waf/index.py
  12. 4
      plugins/op_waf/install.sh
  13. 34
      plugins/op_waf/js/op_waf.js
  14. 7
      plugins/op_waf/t/cc.py
  15. 166
      plugins/op_waf/t/index.py
  16. 2
      plugins/op_waf/t/test.sh
  17. 2
      plugins/op_waf/waf/config.json
  18. 186
      plugins/op_waf/waf/lua/common.lua
  19. 293
      plugins/op_waf/waf/lua/init.lua
  20. 2
      plugins/op_waf/waf/rule/user_agent.json
  21. 2
      plugins/op_waf/waf/total.json
  22. 39
      plugins/php-apt/index.html
  23. 182
      plugins/php-apt/index.py
  24. 145
      plugins/php-apt/js/php.js
  25. 38
      plugins/php-yum/index.html
  26. 182
      plugins/php-yum/index.py
  27. 141
      plugins/php-yum/js/php.js
  28. 39
      plugins/php/index.html
  29. 179
      plugins/php/index.py
  30. 160
      plugins/php/js/php.js
  31. 2
      plugins/redis/config/redis.conf
  32. 16
      plugins/redis/index.py
  33. 1
      plugins/redis/init.d/redis.service.tpl
  34. 5
      plugins/redis/js/redis.js
  35. 15
      plugins/swap/index.py
  36. 10
      route/static/app/config.js
  37. 2
      route/static/app/control.js
  38. 6
      route/static/app/crontab.js
  39. 20
      route/static/app/files.js
  40. 16
      route/static/app/index.js
  41. 18
      route/static/app/public.js
  42. 28
      route/static/app/site.js
  43. 6
      route/static/app/soft.js
  44. 19
      scripts/init.d/mw.tpl
  45. 5
      scripts/logs_backup.py

@ -90,16 +90,15 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
``` ```
### 版本更新 0.9.12 ### 版本更新 0.9.13
* 日志清理插件优化。 * 优化弹框。
* 计划任务显示完整。 * 修复计划任务[日志切割]。
* 加入gitea插件。 * 优化mysql的与phpmyadmin的连接。
* 融合mw-cli命令。 * PHP添加`会话管理`功能。
* 加快php编译速度。 * redis优化。
* swap加上调整功能。 * 更新mysql[5.7]的安装。
* 其他细节优化。 * OP防火墙部分功能优化。
### JSDelivr安装地址 ### JSDelivr安装地址

@ -15,7 +15,7 @@ from flask import request
class config_api: class config_api:
__version = '0.9.12' __version = '0.9.13'
def __init__(self): def __init__(self):
pass pass

@ -98,6 +98,7 @@ def initConf():
"/var/log/secure", "/var/log/secure",
"/var/log/lastlog", "/var/log/lastlog",
"/var/log/cron", "/var/log/cron",
"/www/server/cron"
] ]
for i in clogcom: for i in clogcom:
if os.path.exists(i): if os.path.exists(i):

@ -23,8 +23,6 @@ Install_app()
echo '正在安装脚本文件...' > $install_tmp echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/clean mkdir -p $serverPath/clean
echo "" > $serverPath/clean/clean.conf
cd ${rootPath} && python3 ${rootPath}/plugins/clean/index.py start cd ${rootPath} && python3 ${rootPath}/plugins/clean/index.py start
echo "${VERSION}" > $serverPath/clean/version.pl echo "${VERSION}" > $serverPath/clean/version.pl
echo '安装完成' > $install_tmp echo '安装完成' > $install_tmp

@ -88,16 +88,18 @@ def createBgTaskByName(name, args):
_where1 = args['minute-n'] _where1 = args['minute-n']
_minute = '' _minute = ''
mw_dir = mw.getRunDir()
cmd = ''' cmd = '''
mw_dir=%s
rname=%s rname=%s
plugin_path=%s plugin_path=%s
script_path=%s script_path=%s
logs_file=$plugin_path/${rname}.log logs_file=$plugin_path/${rname}.log
''' % (name, getServerDir(), getPluginDir()) ''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n" cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n" cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
cmd += 'echo "python3 $script_path/index.py clean >> $logs_file 2>&1"' + "\n" cmd += 'echo "python3 $script_path/index.py clean >> $logs_file 2>&1"' + "\n"
cmd += 'python3 $script_path/index.py clean >> $logs_file 2>&1' + "\n" cmd += 'cd $mw_dir && python3 $script_path/index.py clean >> $logs_file 2>&1' + "\n"
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n" cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n" cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"

@ -817,6 +817,7 @@ function openPhpmyadmin(name,username,password){
layer.msg('当前为['+rdata.choose+']模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']}); layer.msg('当前为['+rdata.choose+']模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
return; return;
} }
var phpmyadmin_cfg = rdata;
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'}); data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
var rdata = $.parseJSON(data.data); var rdata = $.parseJSON(data.data);
@ -824,7 +825,10 @@ function openPhpmyadmin(name,username,password){
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']}); layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
return; return;
} }
$("#toPHPMyAdmin").attr('action',rdata.data);
var home_page = rdata.data;
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@");
$("#toPHPMyAdmin").attr('action',home_page);
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){ if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']}); layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});

@ -68,6 +68,26 @@ function myAsyncPost(method,args){
return syncPost('/plugins/run', {name:'mysql', func:method, args:_args}); return syncPost('/plugins/run', {name:'mysql', func:method, args:_args});
} }
function vaildPhpmyadmin(url,username,password){
console.log("Authorization: Basic " + btoa(username + ":" + password));
$.ajax({
type: "GET",
url: url,
dataType: 'json',
async: false,
username:username,
password:password,
headers: {
"Authorization": "Basic " + btoa(username + ":" + password)
},
data: 'vaild',
success: function (){
alert('Thanks for your comment!');
}
});
}
function runInfo(){ function runInfo(){
myPost('run_info','',function(data){ myPost('run_info','',function(data){
@ -819,15 +839,18 @@ function openPhpmyadmin(name,username,password){
return; return;
} }
// console.log(data); var phpmyadmin_cfg = rdata;
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'}); data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
var rdata = $.parseJSON(data.data); var rdata = $.parseJSON(data.data);
if (!rdata.status){ if (!rdata.status){
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']}); layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
return; return;
} }
$("#toPHPMyAdmin").attr('action',rdata.data); var home_page = rdata.data;
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@")
$("#toPHPMyAdmin").attr('action',home_page);
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){ if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']}); layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});
setTimeout(function(){ window.location.href = '/soft'; },3000); setTimeout(function(){ window.location.href = '/soft'; },3000);
@ -836,7 +859,7 @@ function openPhpmyadmin(name,username,password){
//检查版本 //检查版本
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'version'}); data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'version'});
bigVer = data.data.split('.')[0] bigVer = data.data.split('.')[0];
if (bigVer>=4.5){ if (bigVer>=4.5){
setTimeout(function(){ setTimeout(function(){

@ -17,7 +17,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mysqlDir=${serverPath}/source/mysql mysqlDir=${serverPath}/source/mysql
VERSION="5.7.37" VERSION="5.7.39"
Install_mysql() Install_mysql()
@ -68,7 +68,7 @@ Install_mysql()
fi fi
#检测文件是否损坏. #检测文件是否损坏.
md5_mysql_ok=d0489fc3880248a58759c50bfb286dbb md5_mysql_ok=db1b672fc257bd46356c7af26dd22801
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'` md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then

@ -1,6 +1,6 @@
lua_shared_dict limit 30m; lua_shared_dict limit 30m;
lua_shared_dict drop_ip 30m; lua_shared_dict drop_ip 10m;
lua_shared_dict drop_sum 30m; lua_shared_dict drop_sum 10m;
lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;"; lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
access_by_lua_file {$WAF_PATH}/lua/init.lua; access_by_lua_file {$WAF_PATH}/lua/init.lua;

@ -232,7 +232,7 @@
<p onclick="wafGloabl();">全局配置</p> <p onclick="wafGloabl();">全局配置</p>
<p onclick="wafSite();">站点配置</p> <p onclick="wafSite();">站点配置</p>
<p onclick="wafHistory();">封锁历史</p> <p onclick="wafHistory();">封锁历史</p>
<!-- <p onclick="wafLogs();">操作日志</p> --> <p onclick="wafLogs();">操作日志</p>
</div> </div>
<!-- lib-con --> <!-- lib-con -->
<div class="bt-w-con pd15"> <div class="bt-w-con pd15">

@ -111,7 +111,7 @@ def initSiteInfo():
tmp['log'] = True tmp['log'] = True
tmp['get'] = True tmp['get'] = True
tmp['post'] = True tmp['post'] = True
tmp['open'] = False tmp['open'] = True
tmp['cc'] = config_contents['cc'] tmp['cc'] = config_contents['cc']
tmp['retry'] = config_contents['retry'] tmp['retry'] = config_contents['retry']
@ -122,7 +122,22 @@ def initSiteInfo():
tmp['scan'] = config_contents['scan'] tmp['scan'] = config_contents['scan']
cdn_header = ['x-forwarded-for', cdn_header = ['x-forwarded-for',
'x-real-ip', 'HTTP_CF_CONNECTING_IP'] 'x-real-ip',
'x-forwarded',
'forwarded-for',
'forwarded',
'true-client-ip',
'client-ip',
'ali-cdn-real-ip',
'cdn-src-ip',
'cdn-real-ip',
'cf-connecting-ip',
'cf-connecting-ip',
'x-cluster-client-ip',
'wl-proxy-client-ip',
'proxy-client-ip',
'true-client-ip',
'HTTP_CF_CONNECTING_IP']
tmp['cdn_header'] = cdn_header tmp['cdn_header'] = cdn_header
disable_upload_ext = ["php", "jsp"] disable_upload_ext = ["php", "jsp"]
@ -163,6 +178,7 @@ def initTotalInfo():
tmp['get'] = 0 tmp['get'] = 0
tmp['post'] = 0 tmp['post'] = 0
tmp['total'] = 0 tmp['total'] = 0
tmp['url_ext'] = 0
_name = {} _name = {}
_name[name] = tmp _name[name] = tmp
total_contents['sites'] = _name total_contents['sites'] = _name
@ -186,10 +202,12 @@ def status():
def contentReplace(content): def contentReplace(content):
service_path = mw.getServerDir() service_path = mw.getServerDir()
waf_path = getServerDir() + "/waf" waf_root = getServerDir()
waf_path = waf_root + "/waf"
content = content.replace('{$ROOT_PATH}', mw.getRootDir()) content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path) content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$WAF_PATH}', waf_path) content = content.replace('{$WAF_PATH}', waf_path)
content = content.replace('{$WAF_ROOT}', waf_root)
return content return content
@ -201,6 +219,14 @@ def initDreplace():
cmd = 'cp -rf ' + sdir + ' ' + path cmd = 'cp -rf ' + sdir + ' ' + path
mw.execShell(cmd) mw.execShell(cmd)
logs_path = path + '/logs'
if not os.path.exists(logs_path):
mw.execShell('mkdir -p ' + logs_path)
debug_log = path + '/debug.log'
if not os.path.exists(debug_log):
mw.execShell('echo "" > ' + debug_log)
config = path + '/waf/config.json' config = path + '/waf/config.json'
content = mw.readFile(config) content = mw.readFile(config)
content = json.loads(content) content = json.loads(content)
@ -214,6 +240,11 @@ def initDreplace():
content = contentReplace(content) content = contentReplace(content)
mw.writeFile(config, content) mw.writeFile(config, content)
config_common = path + "/waf/lua/common.lua"
content = mw.readFile(config_common)
content = contentReplace(content)
mw.writeFile(config_common, content)
waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf" waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf"
waf_tpl = getPluginDir() + "/conf/luawaf.conf" waf_tpl = getPluginDir() + "/conf/luawaf.conf"
content = mw.readFile(waf_tpl) content = mw.readFile(waf_tpl)
@ -224,6 +255,9 @@ def initDreplace():
initSiteInfo() initSiteInfo()
initTotalInfo() initTotalInfo()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + path)
def start(): def start():
initDreplace() initDreplace()
@ -800,7 +834,7 @@ def getLogsList():
return data[1] return data[1]
data = [] data = []
path = mw.getLogsDir() + '/waf' path = getServerDir() + '/logs'
if not os.path.exists(path): if not os.path.exists(path):
return mw.returnJson(False, '还未生成!', []) return mw.returnJson(False, '还未生成!', [])
@ -823,7 +857,7 @@ def getSafeLogs():
if not data[0]: if not data[0]:
return data[1] return data[1]
path = mw.getLogsDir() + '/waf' path = getServerDir() + '/logs'
file = path + '/' + args['siteName'] + '_' + args['toDate'] + '.log' file = path + '/' + args['siteName'] + '_' + args['toDate'] + '.log'
if not os.path.exists(file): if not os.path.exists(file):
return mw.returnJson(False, "文件不存在!") return mw.returnJson(False, "文件不存在!")

@ -19,12 +19,12 @@ Install_of(){
echo '0.1' > $serverPath/op_waf/version.pl echo '0.1' > $serverPath/op_waf/version.pl
echo 'install ok' > $install_tmp echo 'install ok' > $install_tmp
cd ${rootPath} && python3 plugins/op_waf/index.py start cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py start
} }
Uninstall_of(){ Uninstall_of(){
cd ${rootPath} && python3 plugins/op_waf/index.py stop cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop
rm -rf $serverPath/op_waf rm -rf $serverPath/op_waf
} }

@ -28,7 +28,7 @@ function setRequestCode(ruleName, statusCode){
title: "设置响应代码【" + ruleName + "】", title: "设置响应代码【" + ruleName + "】",
area: '300px', area: '300px',
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
shadeClose: true, shadeClose: true,
content: '<div class="bt-form pd20 pb70">\ content: '<div class="bt-form pd20 pb70">\
<div class="line">\ <div class="line">\
@ -144,7 +144,7 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
type: 1, type: 1,
title: "设置CC规则", title: "设置CC规则",
area: '540px', area: '540px',
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<form class="bt-form pd20 pb70">\ content: '<form class="bt-form pd20 pb70">\
<div class="line">\ <div class="line">\
@ -184,7 +184,7 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
type: 1, type: 1,
title: "设置恶意容忍规则", title: "设置恶意容忍规则",
area: '500px', area: '500px',
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<form class="bt-form pd20 pb70">\ content: '<form class="bt-form pd20 pb70">\
<div class="line">\ <div class="line">\
@ -339,7 +339,7 @@ function setObjConf(ruleName, type) {
type: 1, type: 1,
title: "编辑规则【" + ruleName + "】", title: "编辑规则【" + ruleName + "】",
area: ['700px', '530px'], area: ['700px', '530px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15">\ content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\ <div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -405,7 +405,7 @@ function scanRule() {
type: 1, type: 1,
title: "常用扫描器过滤规则", title: "常用扫描器过滤规则",
area: '650px', area: '650px',
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<form class="bt-form pd20 pb70">\ content: '<form class="bt-form pd20 pb70">\
<div class="line">\ <div class="line">\
@ -571,7 +571,7 @@ function ipWhite(type) {
type: 1, type: 1,
title: "管理IP白名单", title: "管理IP白名单",
area: ['500px', '500px'], area: ['500px', '500px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15 ipv4_list">\ content: '<div class="pd15 ipv4_list">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\ <div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -714,7 +714,7 @@ function ipBlack(type) {
type: 1, type: 1,
title: "管理IP黑名单", title: "管理IP黑名单",
area: ['500px', '500px'], area: ['500px', '500px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="tab_list"><div class="tab_block active">IPv4黑名单</div><div class="tab_block">IPv6</div></div>\ content: '<div class="tab_list"><div class="tab_block active">IPv4黑名单</div><div class="tab_block">IPv6</div></div>\
<div class="pd15 ipv4_block">\ <div class="pd15 ipv4_block">\
@ -824,12 +824,12 @@ function wafScreen(){
<div class="line"><span class="name">CC攻击</span><span class="val">'+rdata.rules.cc+'</span></div>\ <div class="line"><span class="name">CC攻击</span><span class="val">'+rdata.rules.cc+'</span></div>\
<div class="line"><span class="name">恶意User-Agent</span><span class="val">'+rdata.rules.user_agent+'</span></div>\ <div class="line"><span class="name">恶意User-Agent</span><span class="val">'+rdata.rules.user_agent+'</span></div>\
<div class="line"><span class="name">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\ <div class="line"><span class="name">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">0</span></div>\ <div class="line"><span class="name">恶意扫描</span><span class="val">'+rdata.rules.scan+'</span></div>\
<div class="line"><span class="name">恶意HEAD请求</span><span class="val">0</span></div>\ <div class="line"><span class="name">恶意HEAD请求</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">0</span></div>\ <div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">URI保护</span><span class="val">0</span></div>\ <div class="line"><span class="name">URI保护</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">恶意文件上传</span><span class="val">0</span></div>\ <div class="line"><span class="name">恶意文件上传</span><span class="val">0</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">0</span></div>\ <div class="line"><span class="name">禁止的扩展名</span><span class="val">'+rdata.rules.url_ext+'</span></div>\
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">0</span></div>\ <div class="line"><span class="name">禁止PHP脚本</span><span class="val">0</span></div>\
</div>'; </div>';
@ -975,7 +975,7 @@ function siteWafLog(siteName) {
type: 1, type: 1,
title: "日志【" + siteName + "】", title: "日志【" + siteName + "】",
area: ['880px', '500px'], area: ['880px', '500px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="lib-box pd15 lib-box-log">\ content: '<div class="lib-box pd15 lib-box-log">\
<div class="lib-con-title" style="height:40px"><select id="selectLogDay" class="bt-input-text" onchange="siteLogCon(\''+ siteName + '\',this.options[this.options.selectedIndex].value,1)">' + selectLogDay + '</select></div>\ <div class="lib-con-title" style="height:40px"><select id="selectLogDay" class="bt-input-text" onchange="siteLogCon(\''+ siteName + '\',this.options[this.options.selectedIndex].value,1)">' + selectLogDay + '</select></div>\
@ -1071,7 +1071,7 @@ function siteLogCon(siteName, day, page) {
type: 1, type: 1,
title: time + "详情", title: time + "详情",
area: '600px', area: '600px',
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15 lib-box">\ content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\ <table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
@ -1190,7 +1190,7 @@ function siteRuleAdmin(siteName, ruleName, type) {
type: 1, type: 1,
title: "管理网站过滤规则【" + title + "】", title: "管理网站过滤规则【" + title + "】",
area: ['500px', '500px'], area: ['500px', '500px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15">\ content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\ <div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -1237,7 +1237,7 @@ function cdnHeader(siteName, type) {
type: 1, type: 1,
title: "管理网站【" + siteName + "】CDN-Headers", title: "管理网站【" + siteName + "】CDN-Headers",
area: ['500px', '500px'], area: ['500px', '500px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15">\ content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\ <div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@ -1342,7 +1342,7 @@ function setSiteObjConf(siteName, ruleName, type) {
type: 1, type: 1,
title: "编辑网站【" + siteName + "】规则【" + ruleName + "】", title: "编辑网站【" + siteName + "】规则【" + ruleName + "】",
area: ['700px', '530px'], area: ['700px', '530px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15">\ content: '<div class="pd15">\
<div class="divtable">\ <div class="divtable">\
@ -1394,7 +1394,7 @@ function siteWafConfig(siteName, type) {
type: 1, type: 1,
title: "网站配置【" + siteName + "】", title: "网站配置【" + siteName + "】",
area: ['700px', '500px'], area: ['700px', '500px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div id="s_w_c"></div>' content: '<div id="s_w_c"></div>'
}); });

@ -1,7 +0,0 @@
# coding:utf-8
import sys
import io
import os
import time
import json

@ -6,14 +6,168 @@ import os
import time import time
import json import json
import os
import sys
import time
import string
import json
import hashlib
import shlex
import datetime
import subprocess
import re
from random import Random
TEST_URL = "http://t1.cn/"
# TEST_URL = "https://www.zzzvps.com/"
def httpGet(url, timeout=10):
import urllib.request
try:
req = urllib.request.urlopen(url, timeout=timeout)
result = req.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpGet__UA(url, ua, timeout=10):
import urllib.request
headers = {'user-agent': ua}
try:
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req)
result = response.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpPost(url, data, timeout=10):
"""
发送POST请求
@url 被请求的URL地址(必需)
@data POST参数可以是字符串或字典(必需)
@timeout 超时时间默认60秒
return string
"""
if sys.version_info[0] == 2:
try:
import urllib
import urllib2
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.urlencode(data)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req, timeout=timeout)
return response.read()
except Exception as ex:
return str(ex)
else:
try:
import urllib.request
import ssl
try:
ssl._create_default_https_context = ssl._create_unverified_context
except:
pass
data = urllib.parse.urlencode(data).encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req, timeout=timeout)
result = response.read()
if type(result) == bytes:
result = result.decode('utf-8')
return result
except Exception as ex:
return str(ex)
def test_Dir():
'''
目录保存
'''
url = TEST_URL + '?t=../etc/passwd'
print("args test start")
url_val = httpGet(url, 10)
# print(url_val)
print("args test end")
def test_UA():
'''
user-agent 过滤
'''
url = TEST_URL
print("user-agent test start")
url_val = httpGet__UA(url, 'ApacheBench')
print(url_val)
print("user-agent test end")
def test_POST():
'''
user-agent 过滤
'''
url = TEST_URL
print("POST test start")
url_val = httpPost(url, {'data': "substr($mmsss,0,1)"})
# url_val = httpPost(url, {'data': "123123"})
print(url_val)
print("POST test end")
def test_scan():
'''
目录保存
'''
url = TEST_URL + '/acunetix_wvs_security_test?t=1'
print("scan test start")
url_val = httpGet(url, 10)
print(url_val)
print("scan test end")
def test_CC():
'''
目录保存
'''
url = TEST_URL + 'ok.txt'
print("CC test start")
for x in range(122):
url_val = httpGet(url, 10)
print(url_val)
print("CC test end")
def test_url_ext():
'''
目录保存
'''
url = TEST_URL + 't.sql'
print("url_ext start")
url_val = httpGet(url, 10)
print(url_val)
print("url_ext end")
TEST_URL = "t1.cn"
def test_start():
# test_Dir()
# test_UA()
# test_POST()
# test_scan()
# test_CC()
test_url_ext()
def run():
print('op lua run ok')
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) > 1: os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/op_waf && sh install.sh uninstall 0.1 && sh install.sh install 0.1')
if action == "run": os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/ && python3 plugins/openresty/index.py stop && python3 plugins/openresty/index.py start')
run() test_start()

@ -2,6 +2,8 @@
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH export PATH
# yum -y install httpd-tools
# ab -c 1000 -n 1000000 http://xx.xx.xx/
python3 index.py python3 index.py

@ -1 +1 @@
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "\u8fc7\u6ee4\u5e38\u89c1\u626b\u63cf\u6d4b\u8bd5\u5de5\u5177\u7684\u6e17\u900f\u6d4b\u8bd5", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "\u8fc7\u8651CC\u653b\u51fb", "limit": 120, "endtime": 300, "open": true, "reqfile": "", "cycle": 60}, "get": {"status": 403, "ps": "\u8fc7\u6ee4uri\u3001uri\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 403, "ps": "\u901a\u5e38\u7528\u4e8e\u8fc7\u6ee4\u6d4f\u89c8\u5668\u3001\u8718\u86db\u53ca\u4e00\u4e9b\u81ea\u52a8\u626b\u63cf\u5668", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 403, "ps": "\u5176\u5b83\u975e\u901a\u7528\u8fc7\u6ee4", "reqfile": "other.html"}, "cookie": {"status": 403, "ps": "\u8fc7\u6ee4\u5229\u7528Cookie\u53d1\u8d77\u7684\u6e17\u900f\u653b\u51fb", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/btwaf", "post": {"status": 403, "ps": "\u8fc7\u6ee4POST\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "post.html"}, "open": true} {"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "\u8fc7\u6ee4\u5e38\u89c1\u626b\u63cf\u6d4b\u8bd5\u5de5\u5177\u7684\u6e17\u900f\u6d4b\u8bd5", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "\u8fc7\u8651CC\u653b\u51fb", "limit": 120, "endtime": 300, "open": true, "reqfile": "", "cycle": 60}, "get": {"status": 403, "ps": "\u8fc7\u6ee4uri\u3001uri\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 403, "ps": "\u901a\u5e38\u7528\u4e8e\u8fc7\u6ee4\u6d4f\u89c8\u5668\u3001\u8718\u86db\u53ca\u4e00\u4e9b\u81ea\u52a8\u626b\u63cf\u5668", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 403, "ps": "\u5176\u5b83\u975e\u901a\u7528\u8fc7\u6ee4", "reqfile": "other.html"}, "cookie": {"status": 403, "ps": "\u8fc7\u6ee4\u5229\u7528Cookie\u53d1\u8d77\u7684\u6e17\u900f\u653b\u51fb", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/waf", "post": {"status": 403, "ps": "\u8fc7\u6ee4POST\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "post.html"}, "open": true}

@ -1,26 +1,89 @@
local setmetatable = setmetatable local setmetatable = setmetatable
local _M = { _VERSION = '0.01' } local _M = { _VERSION = '0.02' }
local mt = { __index = _M } local mt = { __index = _M }
local json = require "cjson" local json = require "cjson"
local ngx_match = ngx.re.find local ngx_match = ngx.re.find
local debug_mode = false
local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/"
local logdir = waf_root.."/logs/"
local rpath = cpath.."/rule/"
function _M.new(self)
function _M.new(self, cpath, rpath, logdir) local self = {
-- ngx.log(ngx.ERR,"read:"..cpath..",rpath:"..rpath) waf_root = waf_root,
local opt = {
cpath = cpath, cpath = cpath,
rpath = rpath, rpath = rpath,
logdir = logdir, logdir = logdir,
config = '', config = '',
site_config = '', site_config = '',
server_name = '',
params = nil params = nil
} }
local p = setmetatable(opt, mt)
return p return setmetatable(self, mt)
end
function _M.setDebug(self, mode)
debug_mode = mode
end
-- 调试方式
function _M.D(self, msg)
if not debug_mode then return true end
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = tostring( key)..':'.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
local fp = io.open(waf_root.."/debug.log", "ab")
if fp == nil then
return nil
end
local localtime = os.date("%Y-%m-%d %H:%M:%S")
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end end
local function write_file_clear(filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
end
function _M.setConfData( self, config, site_config ) function _M.setConfData( self, config, site_config )
self.config = config self.config = config
self.site_config = site_config self.site_config = site_config
@ -94,6 +157,10 @@ function _M.compare_ip(self,ips)
end end
function _M.to_json(self, msg)
return json.encode(msg)
end
function _M.return_message(self, status, msg) function _M.return_message(self, status, msg)
ngx.header.content_type = "application/json;" ngx.header.content_type = "application/json;"
ngx.status = status ngx.status = status
@ -136,20 +203,15 @@ function _M.write_file(self, filename, body)
return true return true
end end
function _M.write_file_clear(self, filename, body) function _M.write_file_clear(self, filename, body)
fp = io.open(filename,'w') return write_file_clear(filename, body)
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
end end
function _M.write_drop_ip(self, is_drop, drop_time) function _M.write_drop_ip(self, is_drop, drop_time)
local filename = self.cpath .. 'drop_ip.log' local filename = self.logdir .. 'drop_ip.log'
local fp = io.open(filename,'ab') local fp = io.open(filename,'ab')
local server_name = self.params["server_name"] local server_name = self.params["server_name"]
local ip = self.params["server_name"] local ip = self.params["server_name"]
@ -234,11 +296,21 @@ function _M.read_file(self, name)
end end
function _M.read_file_table( self, name ) function _M.read_file_table( self, name )
return self:select_rule(self:read_file('args')) return self:select_rule(self:read_file(name))
end end
local function timer_at_inc_log(premature)
local total_path = cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path)
if not tbody then
return false
end
return write_file_clear(total_path,tbody)
end
function _M.inc_log(self, name, rule) function _M.inc_log(self, name, rule)
local server_name = self.params['server_name'] local server_name = self.params['server_name']
local total_path = self.cpath .. 'total.json' local total_path = self.cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path) local tbody = ngx.shared.limit:get(total_path)
@ -246,7 +318,10 @@ function _M.inc_log(self, name, rule)
tbody = self:read_file_body(total_path) tbody = self:read_file_body(total_path)
if not tbody then return false end if not tbody then return false end
end end
local total = json.decode(tbody) local total = json.decode(tbody)
-- 开始计算
if not total['sites'] then total['sites'] = {} end if not total['sites'] then total['sites'] = {} end
if not total['sites'][server_name] then total['sites'][server_name] = {} end if not total['sites'][server_name] then total['sites'][server_name] = {} end
if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end
@ -256,13 +331,15 @@ function _M.inc_log(self, name, rule)
total['total'] = total['total'] + 1 total['total'] = total['total'] + 1
total['sites'][server_name][name] = total['sites'][server_name][name] + 1 total['sites'][server_name][name] = total['sites'][server_name][name] + 1
total['rules'][name] = total['rules'][name] + 1 total['rules'][name] = total['rules'][name] + 1
local total_log = json.encode(total) local total_log = json.encode(total)
if not total_log then return false end if not total_log then return false end
ngx.shared.limit:set(total_path,total_log) ngx.shared.limit:set(total_path,total_log)
if not ngx.shared.limit:get('mw_waf_timeout') then
self:write_file_clear(total_path,total_log) -- 异步执行
ngx.shared.limit:set('mw_waf_timeout',1,5) ngx.timer.at(1, timer_at_inc_log)
end
end end
@ -289,9 +366,66 @@ function _M.get_server_name(self)
end end
-- function _M.get_sn(self)
-- retun string.gsub(self:get_server_name(),'_','.') function _M.is_ngx_match_orgin(self,rule,match, sign)
-- end if ngx_match(ngx.unescape_uri(match), rule,"isjo") then
error_rule = rule .. ' >> ' .. sign .. ':' .. match
return true
end
return false
end
function _M.ngx_match_string(self, rule, content,sign)
local t = self:is_ngx_match_orgin(rule, content, sign)
if t then
return true
end
return false
end
function _M.ngx_match_list(self, rules, content)
for i,rule in ipairs(rules)
do
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match_ua(self, rules, content)
-- ngx.header.content_type = "text/html"
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match_post(self, rules, content)
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2],content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match(self, rules, sbody, rule_name) function _M.is_ngx_match(self, rules, sbody, rule_name)
@ -341,6 +475,7 @@ end
function _M.write_log(self, name, rule) function _M.write_log(self, name, rule)
local ip = self.params['ip'] local ip = self.params['ip']
local retry = self.config['retry']['retry'] local retry = self.config['retry']['retry']
local retry_time = self.config['retry']['retry_time'] local retry_time = self.config['retry']['retry_time']
@ -352,6 +487,7 @@ function _M.write_log(self, name, rule)
else else
ngx.shared.drop_ip:set(ip,1,retry_cycle) ngx.shared.drop_ip:set(ip,1,retry_cycle)
end end
if self.config['log'] ~= true or self:is_site_config('log') ~= true then return false end if self.config['log'] ~= true or self:is_site_config('log') ~= true then return false end
local method = ngx.req.get_method() local method = ngx.req.get_method()
if error_rule then if error_rule then
@ -384,10 +520,13 @@ end
function _M.get_client_ip(self) function _M.get_client_ip(self)
local client_ip = "unknown" local client_ip = "unknown"
local server_name = self.params['server_name']
-- self:D("fff..."..client_ip..server_name)
if self.site_config[server_name] then if self.site_config[server_name] then
if self.site_config[server_name]['cdn'] then if self.site_config[server_name]['cdn'] then
for _,v in ipairs(self.site_config[server_name]['cdn_header']) for _,v in ipairs(self.site_config[server_name]['cdn_header'])
do do
-- C:D("vv:"..v..tostring(request_header[v]))
if request_header[v] ~= nil and request_header[v] ~= "" then if request_header[v] ~= nil and request_header[v] ~= "" then
local header_tmp = request_header[v] local header_tmp = request_header[v]
if type(header_tmp) == "table" then header_tmp = header_tmp[1] end if type(header_tmp) == "table" then header_tmp = header_tmp[1] end
@ -408,7 +547,6 @@ end
function _M.is_site_config(self,cname) function _M.is_site_config(self,cname)
local server_name = self.params["server_name"]
if self.site_config[server_name] ~= nil then if self.site_config[server_name] ~= nil then
if cname == 'cc' then if cname == 'cc' then
return self.site_config[server_name][cname]['open'] return self.site_config[server_name][cname]['open']

@ -1,65 +1,55 @@
local cpath = "{$WAF_PATH}/"
local rpath = "{$WAF_PATH}/rule/"
local logdir = "{$ROOT_PATH}/wwwlogs/waf/"
local json = require "cjson" local json = require "cjson"
local ngx_match = ngx.re.find local ngx_match = ngx.re.find
local _C = require "common" local __C = require "common"
local C = _C:new(cpath, rpath, logdir) local C = __C:new()
local waf_root = "{$WAF_ROOT}"
config = C:read_file_body_decode(cpath .. 'config.json') config = C:read_file_body_decode(waf_root.."/waf/"..'config.json')
local site_config = C:read_file_body_decode(cpath .. 'site.json') local site_config = C:read_file_body_decode(waf_root.."/waf/"..'site.json')
C:setConfData(config, site_config) C:setConfData(config, site_config)
-- D func
local function D(msg)
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = key..':'..val.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
if not debug_mode then return true end
local fp = io.open(cpath..'debug.log', 'ab')
if fp == nil then
return nil
end
local localtime = os.date("%Y-%m-%d %H:%M:%S")
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"])
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
local args_rules = C:read_file_table('args')
local ip_white_rules = C:read_file('ip_white')
local ip_black_rules = C:read_file('ip_black')
local scan_black_rules = C:read_file('scan_black')
local user_agent_rules = C:read_file('user_agent')
local post_rules = C:read_file('post')
local cookie_rules = C:read_file('cookie')
local server_name = string.gsub(C:get_server_name(),'_','.')
-- C:D("sss:"..C:get_server_name())
function initParams() function initParams()
local data = {} local data = {}
data['ip'] = C:get_client_ip() data['server_name'] = server_name
data['ipn'] = C:arrip(data['ip']) -- data['ip'] = C:get_client_ip()
-- data['ipn'] = C:arrip(data['ip'])
data['request_header'] = ngx.req.get_headers() data['request_header'] = ngx.req.get_headers()
data['uri'] = ngx.unescape_uri(ngx.var.uri) data['uri'] = ngx.unescape_uri(ngx.var.uri)
data['server_name'] = string.gsub(C:get_server_name(),'_','.')
data['uri_request_args'] = ngx.req.get_uri_args() data['uri_request_args'] = ngx.req.get_uri_args()
data['method'] = ngx.req.get_method() data['method'] = ngx.req.get_method()
data['request_uri'] = ngx.var.request_uri data['request_uri'] = ngx.var.request_uri
data['cookie'] = ngx.var.http_cookie
return data return data
end end
local params = initParams() local params = initParams()
C:setParams(params) C:setParams(params)
C:setDebug(true)
local server_name = params["server_name"]
params['ip'] = C:get_client_ip()
params['ipn'] = C:arrip(params['ip'])
C:D(server_name)
function get_return_state(rstate,rmsg) function get_return_state(rstate,rmsg)
result = {} result = {}
@ -102,7 +92,7 @@ function save_ip_on(data)
end end
end end
function remove_btwaf_drop_ip() function remove_waf_drop_ip()
if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip') ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
@ -125,7 +115,7 @@ function remove_btwaf_drop_ip()
return get_return_state(true,uri_request_args['ip'] .. '已解封') return get_return_state(true,uri_request_args['ip'] .. '已解封')
end end
function clean_btwaf_drop_ip() function clean_waf_drop_ip()
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip') ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data2=json.decode(ret2) ip_data2=json.decode(ret2)
@ -155,15 +145,7 @@ function min_route()
end end
end end
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"]) function waf_get_args()
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
local args_rules = C:read_file_table('args')
local ip_white_rules = C:read_file('ip_white')
local ip_black_rules = C:read_file('ip_black')
local scan_black_rules = C:read_file('scan_black')
function waf_args()
if not config['get']['open'] or not C:is_site_config('get') then return false end if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(args_rules, params['uri_request_args'],'args') then if C:is_ngx_match(args_rules, params['uri_request_args'],'args') then
C:write_log('args','regular') C:write_log('args','regular')
@ -196,6 +178,18 @@ function waf_ip_black()
end end
function waf_user_agent()
-- user_agent 过滤
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
if C:is_ngx_match_ua(user_agent_rules,params['request_header']['user-agent']) then
C:write_log('user_agent','regular')
C:return_html(config['user-agent']['status'],user_agent_html)
return true
end
return false
end
function waf_drop() function waf_drop()
local count , _ = ngx.shared.drop_ip:get(ip) local count , _ = ngx.shared.drop_ip:get(ip)
if not count then return false end if not count then return false end
@ -206,27 +200,32 @@ function waf_drop()
return false return false
end end
function waf_cc()
local ip = params['ip']
function waf_user_agent() local ip_lock = ngx.shared.drop_ip:get(ip)
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end if ip_lock then
if C:is_ngx_match(user_agent_rules,params['request_header']['user-agent'],'user_agent') then if ip_lock > 0 then
C:write_log('user_agent','regular') ngx.exit(config['cc']['status'])
C:return_html(config['user-agent']['status'],user_agent_html)
return true return true
end end
return false
end end
function cc() if not config['cc']['open'] or not C:is_site_config('cc') then return false end
local ip = params['ip']
local request_uri = params['request_uri'] local request_uri = params['request_uri']
local endtime = config['cc']['endtime'] local endtime = config['cc']['endtime']
if not config['cc']['open'] or not site_cc then return false end
local token = ngx.md5(ip .. '_' .. request_uri) local token = ngx.md5(ip .. '_' .. request_uri)
local count,_ = ngx.shared.limit:get(token) local count = ngx.shared.limit:get(token)
local limit = config['cc']['limit']
local cycle = config['cc']['cycle']
if count then if count then
if count > limit then if count > limit then
local safe_count, _ = ngx.shared.drop_sum:get(ip) local safe_count, _ = ngx.shared.drop_sum:get(ip)
if not safe_count then if not safe_count then
ngx.shared.drop_sum:set(ip,1,86400) ngx.shared.drop_sum:set(ip,1,86400)
@ -236,23 +235,22 @@ function cc()
end end
local lock_time = (endtime * safe_count) local lock_time = (endtime * safe_count)
if lock_time > 86400 then lock_time = 86400 end if lock_time > 86400 then lock_time = 86400 end
ngx.shared.drop_ip:set(ip,retry+1,lock_time)
-- lock_time = 10
ngx.shared.drop_ip:set(ip,1,lock_time)
C:write_log('cc',cycle..'秒内累计超过'..limit..'次请求,封锁' .. lock_time .. '') C:write_log('cc',cycle..'秒内累计超过'..limit..'次请求,封锁' .. lock_time .. '')
C:write_drop_ip('cc',lock_time) C:write_drop_ip('cc',lock_time)
if not server_name then
insert_ip_list(ip,lock_time,os.time(),'1111')
else
insert_ip_list(ip,lock_time,os.time(),server_name)
end
ngx.exit(config['cc']['status']) ngx.exit(config['cc']['status'])
return true return true
else else
ngx.shared.limit:incr(token,1) ngx.shared.limit:incr(token,1)
end end
else else
ngx.shared.drop_sum:set(ip,1,86400)
ngx.shared.limit:set(token, 1, cycle) ngx.shared.limit:set(token, 1, cycle)
end end
return false
end end
--强制验证是否使用正常浏览器访问网站 --强制验证是否使用正常浏览器访问网站
@ -287,20 +285,25 @@ end
function waf_scan_black() function waf_scan_black()
-- 扫描软件禁止
if not config['scan']['open'] or not C:is_site_config('scan') then return false end if not config['scan']['open'] or not C:is_site_config('scan') then return false end
if C:is_ngx_match(scan_black_rules['cookie'],params["request_header"]["cookie"],false) then if not params["cookie"] then
if C:ngx_match_string(scan_black_rules['cookie'], tostring(params["cookie"]),'scan') then
C:write_log('scan','regular') C:write_log('scan','regular')
ngx.exit(config['scan']['status']) ngx.exit(config['scan']['status'])
return true return true
end end
if C:is_ngx_match(scan_black_rules['args'],params["request_uri"],false) then end
if C:ngx_match_string(scan_black_rules['args'], params["request_uri"], 'scan') then
C:write_log('scan','regular') C:write_log('scan','regular')
ngx.exit(config['scan']['status']) ngx.exit(config['scan']['status'])
return true return true
end end
for key,value in pairs(params["request_header"]) for key,value in pairs(params["request_header"])
do do
if C:is_ngx_match(scan_black_rules['header'], key, false) then if C:ngx_match_string(scan_black_rules['header'], key, 'scan') then
C:write_log('scan','regular') C:write_log('scan','regular')
ngx.exit(config['scan']['status']) ngx.exit(config['scan']['status'])
return true return true
@ -309,20 +312,9 @@ function waf_scan_black()
return false return false
end end
function waf_post_referer()
if params['method'] ~= "POST" then return false end
if C:is_ngx_match(referer_local, params['request_header']['Referer'],'post') then
C:write_log('post_referer','regular')
C:return_html(config['post']['status'],post_html)
return true
end
return false
end
function waf_post() function waf_post()
if not config['post']['open'] or not C:is_site_config('post') then return false end if not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end if params['method'] ~= "POST" then return false end
if waf_post_referer() then return true end
content_length = tonumber(params["request_header"]['content-length']) content_length = tonumber(params["request_header"]['content-length'])
max_len = 640 * 1020000 max_len = 640 * 1020000
if content_length > max_len then return false end if content_length > max_len then return false end
@ -333,7 +325,19 @@ function waf_post()
return false return false
end end
if C:is_ngx_match(post_rules,request_args,'post') then for key, val in pairs(request_args) do
if type(val) == "table" then
if type(val[1]) == "boolean" then
return false
end
data = table.concat(val, ", ")
else
data = val
end
end
if C:is_ngx_match_post(post_rules,data) then
C:write_log('post','regular') C:write_log('post','regular')
C:return_html(config['post']['status'],post_html) C:return_html(config['post']['status'],post_html)
return true return true
@ -366,6 +370,7 @@ function post_data_chekc()
end end
if not list_list then return false end if not list_list then return false end
aaa = nil aaa = nil
for k,v in pairs(request_args) for k,v in pairs(request_args)
do do
@ -381,7 +386,7 @@ function post_data_chekc()
if not data_len then return false end if not data_len then return false end
if arrlen(data_len) ==0 then return false end if arrlen(data_len) ==0 then return false end
if C:is_ngx_match(post_rules,data_len,'post') then if C:is_ngx_match_post(post_rules , data_len) then
C:write_log('post','regular') C:write_log('post','regular')
C:return_html(config['post']['status'],post_html) C:return_html(config['post']['status'],post_html)
return true return true
@ -406,7 +411,7 @@ end
function post_X_Forwarded() function post_X_Forwarded()
if not config['post']['open'] or not C:is_site_config('post') then return false end if not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end if params['method'] ~= "POST" then return false end
if C:is_ngx_match(post_rules,params["request_header"]['X-forwarded-For'],'post') then if C:is_ngx_match_post(post_rules,params["request_header"]['X-forwarded-For']) then
C:write_log('post','regular') C:write_log('post','regular')
C:return_html(config['post']['status'],post_html) C:return_html(config['post']['status'],post_html)
return true return true
@ -415,37 +420,37 @@ function post_X_Forwarded()
end end
function php_path() -- function php_path()
if site_config[server_name] == nil then return false end -- if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_php_path']) -- for _,rule in ipairs(site_config[server_name]['disable_php_path'])
do -- do
if ngx_match(uri,rule .. "/?.*\\.php$","isjo") then -- if C:ngx_match_string(params['uri'],rule .. "/?.*\\.php$","isjo") then
C:write_log('php_path','regular') -- C:write_log('php_path','regular')
C:return_html(config['other']['status'],other_html) -- C:return_html(config['other']['status'],other_html)
return C:return_message(200,uri) -- return C:return_message(200,uri)
end -- end
end -- end
return false -- return false
end -- end
function url_path() -- function url_path()
if site_config[server_name] == nil then return false end -- if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_path']) -- for _,rule in ipairs(site_config[server_name]['disable_path'])
do -- do
if ngx_match(uri,rule,"isjo") then -- if ngx_match(uri,rule,"isjo") then
C:write_log('path','regular') -- C:write_log('path','regular')
C:return_html(config['other']['status'],other_html) -- C:return_html(config['other']['status'],other_html)
return true -- return true
end -- end
end -- end
return false -- return false
end -- end
function url_ext() function url_ext()
if site_config[server_name] == nil then return false end if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_ext']) for _,rule in ipairs(site_config[server_name]['disable_ext'])
do do
if ngx_match(uri,"\\."..rule.."$","isjo") then if C:ngx_match_string("\\."..rule.."$", params['uri'],'url_ext') then
C:write_log('url_ext','regular') C:write_log('url_ext','regular')
C:return_html(config['other']['status'], other_html) C:return_html(config['other']['status'], other_html)
return true return true
@ -555,7 +560,7 @@ function waf_cookie()
if not params["request_header"]['cookie'] then return false end if not params["request_header"]['cookie'] then return false end
if type(params["request_header"]['cookie']) ~= "string" then return false end if type(params["request_header"]['cookie']) ~= "string" then return false end
request_cookie = string.lower(params["request_header"]['cookie']) request_cookie = string.lower(params["request_header"]['cookie'])
if C:is_ngx_match(cookie_rules,request_cookie,'cookie') then if C:ngx_match_list(cookie_rules,request_cookie,'cookie') then
C:write_log('cookie','regular') C:write_log('cookie','regular')
C:return_html(config['cookie']['status'],cookie_html) C:return_html(config['cookie']['status'],cookie_html)
return true return true
@ -563,55 +568,45 @@ function waf_cookie()
return false return false
end end
function waf_referer()
if params["method"] ~= "GET" then return false end
if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(referer_local,params["request_header"]['Referer'],'args') then
C:write_log('get_referer','regular')
C:return_html(config['get']['status'], get_html)
return true
end
return false
end
function waf() function waf()
min_route() min_route()
-- white ip
if waf_ip_white() then return true end if waf_ip_white() then return true end
waf_ip_black()
-- black ip
if waf_ip_black() then return true end
waf_drop()
waf_user_agent()
waf_url() -- cc setting
if waf_drop() then return true end
if waf_cc() then return true end
if params["method"] == "GET" then -- ua check
waf_referer() if waf_user_agent() then return true end
waf_cookie() if waf_url() then return true end
end
if params["method"] == "POST" then -- cookie检查
waf_referer() if waf_cookie() then return true end
waf_cookie()
end
waf_args() -- args参数拦截
waf_scan_black() if waf_get_args() then return true end
waf_post() -- 扫描软件禁止
post_data_chekc() if waf_scan_black() then return true end
local server_name = params["server_name"] if waf_post() then return true end
if site_config[server_name] then if post_data_chekc() then return true end
X_Forwarded()
post_X_Forwarded() if site_config[server_name]['open'] then
php_path() if X_Forwarded() then return true end
url_path() if post_X_Forwarded() then return true end
url_ext() -- url_path()
url_rule_ex() if url_ext() then return true end
url_tell() -- url_rule_ex()
post_data() -- url_tell()
-- post_data()
end end
end end

@ -1 +1 @@
[[1, "(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)", "\u5173\u952e\u8bcd\u8fc7\u6ee41", 0]] [[1,"(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)","关键词过滤1",0],[1,"(ApacheBench)","AB测试",0]]

@ -1 +1 @@
{"rules":{"user_agent":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0} {"rules":{"url_ext":0,"user_agent":0,"scan":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0}

@ -1,3 +1,41 @@
<style type="text/css">
.bt-w-main{
height: 600px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form"> <div class="bt-form">
<div class='plugin_version'></div> <div class='plugin_version'></div>
<div class="bt-w-main"> <div class="bt-w-main">
@ -13,6 +51,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p> <p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p> <p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p> <p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p> <p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p> <p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p> <p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>

@ -490,6 +490,180 @@ def getFpmStatus(version):
return mw.returnJson(True, "OK", data) return mw.returnJson(True, "OK", data)
def getSessionConf(version):
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
save_handler = re.search(rep, phpini)
if save_handler:
save_handler = save_handler.group(1)
else:
save_handler = "files"
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
save_path = re.search(reppath, phpini)
if not save_path:
save_path = re.search(memcached, phpini)
passwd = re.search(passrep, phpini)
port = ""
if passwd:
passwd = passwd.group(1)
else:
passwd = ""
if save_path:
port = save_path.group(2)
save_path = save_path.group(1)
else:
save_path = ""
data = {"save_handler": save_handler, "save_path": save_path,
"passwd": passwd, "port": port}
return mw.returnJson(True, 'ok', data)
def setSessionConf(version):
args = getArgs()
ip = args['ip']
port = args['port']
passwd = args['passwd']
save_handler = args['save_handler']
if save_handler != "file":
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址')
try:
port = int(port)
if port >= 65535 or port < 1:
return mw.returnJson(False, '请输入正确的端口号')
except:
return mw.returnJson(False, '请输入正确的端口号')
prep = r"[\~\`\/\=]"
if re.search(prep, passwd):
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
session_tmp = getServerDir() + "/tmp/session"
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
val = r'session.save_handler = ' + save_handler + '\n'
phpini = re.sub(rep, val, phpini)
content = mw.execShell(
'cat /etc/php/' + version + '/fpm/conf.d/*' + " | grep -v '^;' |tr -s '\n'")
content = content[0]
if save_handler == "memcached":
if not re.search("memcached.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "memcache":
if not content.find('memcache') > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "redis":
if not content.find('redis') > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
if passwd:
passwd = "?auth=" + passwd
else:
passwd = ""
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
res = re.search(rep, phpini)
if res:
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "file":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
mw.writeFile(filename, phpini)
reload(version)
return mw.returnJson(True, '设置成功!')
def getSessionCount_Origin(version):
session_tmp = getServerDir() + "/tmp/session"
d = ["/tmp", "/var/lib/php/sessions", session_tmp]
count = 0
for i in d:
if not os.path.exists(i):
mw.execShell('mkdir -p %s' % i)
list = os.listdir(i)
for l in list:
if os.path.isdir(i + "/" + l):
l1 = os.listdir(i + "/" + l)
for ll in l1:
if "sess_" in ll:
count += 1
continue
if "sess_" in l:
count += 1
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
old_file = int(mw.execShell(s)[0].split("\n")[0])
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
old_file += int(mw.execShell(s)[0].split("\n")[0])
return {"total": count, "oldfile": old_file}
def getSessionCount(version):
data = getSessionCount_Origin(version)
return mw.returnJson(True, 'ok!', data)
def cleanSessionOld(version):
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
mw.execShell(s)
session_tmp = getServerDir() + "/tmp/session"
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
mw.execShell(s)
old_file_conf = getSessionCount_Origin(version)["oldfile"]
if old_file_conf == 0:
return mw.returnJson(True, '清理成功')
else:
return mw.returnJson(True, '清理失败')
def getDisableFunc(version): def getDisableFunc(version):
filename = getConf(version) filename = getConf(version)
if not os.path.exists(filename): if not os.path.exists(filename):
@ -688,6 +862,14 @@ if __name__ == "__main__":
print(setFpmConfig(version)) print(setFpmConfig(version))
elif func == 'get_fpm_status': elif func == 'get_fpm_status':
print(getFpmStatus(version)) print(getFpmStatus(version))
elif func == 'get_session_conf':
print(getSessionConf(version))
elif func == 'set_session_conf':
print(setSessionConf(version))
elif func == 'get_session_count':
print(getSessionCount(version))
elif func == 'clean_session_old':
print(cleanSessionOld(version))
elif func == 'get_disable_func': elif func == 'get_disable_func':
print(getDisableFunc(version)) print(getDisableFunc(version))
elif func == 'set_disable_func': elif func == 'set_disable_func':

@ -368,6 +368,151 @@ function disableFunc(version) {
$(".soft-man-con").html(con); $(".soft-man-con").html(con);
}); });
} }
function getSessionConfig(version){
phpPost('get_session_conf', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
var info = rdata.save_path.split(":");
var con = "<div class='conf_p'>" +
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
"</div>\
<ul class='help-info-text c7'>\
<li>若你的站点并发比较高使用RedisMemcache能有效提升PHP并发能力</li>\
<li>若调整Session模式后网站访问异常请切换回原来的模式</li>\
<li>切换Session模式会使在线的用户会话丢失请在流量小的时候切换</li>\
</ul>\
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
</div>\
</div>";
$(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){
$('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
$('input[name="passwd"]').attr('disabled','disabled');
}
// change event
$("select[name='save_handler']").change(function() {
var type = $(this).val();
var passwd = $('input[name="passwd"]').val();
if (passwd == ""){
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
}
var ip = $('input[name="ip"]').val();
if (ip == ""){
$('input[name="ip"]').val('127.0.0.1');
}
switch (type) {
case 'redis':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('6379');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'file':
$('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled');
break;
case 'memcache':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'memcached':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
}
});
//load session stats
phpPost('get_session_count', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
<div class='clear_conter'>\
<div class='session_clear_list'>\
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
</div>\
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
$("#session_clear").html(html_var);
$('#clean_func').click(function(){
phpPost('clean_session_old', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
getSessionConfig(version);
},{ icon: rdata.status ? 1 : 2 });
});
});
});
});
}
function setSessionConfig(version){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var passwd = $('input[name="passwd"]').val();
var save_handler = $("select[name='save_handler']").val();
var data = {
ip:ip,
port:port,
passwd:passwd,
save_handler:save_handler,
};
phpPost('set_session_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//设置禁用函数 //设置禁用函数
function setDisableFunc(version, act, fs) { function setDisableFunc(version, act, fs) {
var fsArr = fs.split(','); var fsArr = fs.split(',');

@ -1,3 +1,40 @@
<style type="text/css">
.bt-w-main{
height: 600px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form"> <div class="bt-form">
<div class='plugin_version'></div> <div class='plugin_version'></div>
<div class="bt-w-main"> <div class="bt-w-main">
@ -13,6 +50,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p> <p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p> <p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p> <p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p> <p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p> <p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p> <p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>

@ -492,6 +492,180 @@ def getFpmStatus(version):
return mw.returnJson(True, "OK", data) return mw.returnJson(True, "OK", data)
def getSessionConf(version):
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
save_handler = re.search(rep, phpini)
if save_handler:
save_handler = save_handler.group(1)
else:
save_handler = "files"
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
save_path = re.search(reppath, phpini)
if not save_path:
save_path = re.search(memcached, phpini)
passwd = re.search(passrep, phpini)
port = ""
if passwd:
passwd = passwd.group(1)
else:
passwd = ""
if save_path:
port = save_path.group(2)
save_path = save_path.group(1)
else:
save_path = ""
data = {"save_handler": save_handler, "save_path": save_path,
"passwd": passwd, "port": port}
return mw.returnJson(True, 'ok', data)
def setSessionConf(version):
args = getArgs()
ip = args['ip']
port = args['port']
passwd = args['passwd']
save_handler = args['save_handler']
if save_handler != "file":
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址')
try:
port = int(port)
if port >= 65535 or port < 1:
return mw.returnJson(False, '请输入正确的端口号')
except:
return mw.returnJson(False, '请输入正确的端口号')
prep = r"[\~\`\/\=]"
if re.search(prep, passwd):
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
session_tmp = getServerDir() + "/tmp/session"
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
val = r'session.save_handler = ' + save_handler + '\n'
phpini = re.sub(rep, val, phpini)
content = mw.execShell('cat /etc/opt/remi/php' +
version + "/php.d/* | grep -v '^;' |tr -s '\n'")
content = content[0]
if save_handler == "memcached":
if not content.find("memcached.so") > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
if save_handler == "memcache":
if not content.find("memcache.so") > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
if save_handler == "redis":
if not content.find("redis.so") > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
if passwd:
passwd = "?auth=" + passwd
else:
passwd = ""
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
res = re.search(rep, phpini)
if res:
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
if save_handler == "file":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
mw.writeFile(filename, phpini)
restart(version)
return mw.returnJson(True, '设置成功!')
def getSessionCount_Origin(version):
session_tmp = getServerDir() + "/tmp/session"
d = ["/tmp", session_tmp]
count = 0
for i in d:
if not os.path.exists(i):
mw.execShell('mkdir -p %s' % i)
list = os.listdir(i)
for l in list:
if os.path.isdir(i + "/" + l):
l1 = os.listdir(i + "/" + l)
for ll in l1:
if "sess_" in ll:
count += 1
continue
if "sess_" in l:
count += 1
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
old_file = int(mw.execShell(s)[0].split("\n")[0])
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
old_file += int(mw.execShell(s)[0].split("\n")[0])
return {"total": count, "oldfile": old_file}
def getSessionCount(version):
data = getSessionCount_Origin(version)
return mw.returnJson(True, 'ok!', data)
def cleanSessionOld(version):
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
mw.execShell(s)
session_tmp = getServerDir() + "/tmp/session"
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
mw.execShell(s)
old_file_conf = getSessionCount_Origin(version)["oldfile"]
if old_file_conf == 0:
return mw.returnJson(True, '清理成功')
else:
return mw.returnJson(True, '清理失败')
def getDisableFunc(version): def getDisableFunc(version):
filename = getConf(version) filename = getConf(version)
if not os.path.exists(filename): if not os.path.exists(filename):
@ -689,6 +863,14 @@ if __name__ == "__main__":
print(setFpmConfig(version)) print(setFpmConfig(version))
elif func == 'get_fpm_status': elif func == 'get_fpm_status':
print(getFpmStatus(version)) print(getFpmStatus(version))
elif func == 'get_session_conf':
print(getSessionConf(version))
elif func == 'set_session_conf':
print(setSessionConf(version))
elif func == 'get_session_count':
print(getSessionCount(version))
elif func == 'clean_session_old':
print(cleanSessionOld(version))
elif func == 'get_disable_func': elif func == 'get_disable_func':
print(getDisableFunc(version)) print(getDisableFunc(version))
elif func == 'set_disable_func': elif func == 'set_disable_func':

@ -340,6 +340,147 @@ function getFpmStatus(version){
}); });
} }
function getSessionConfig(version){
phpPost('get_session_conf', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
var info = rdata.save_path.split(":");
var con = "<div class='conf_p'>" +
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
"</div>\
<ul class='help-info-text c7'>\
<li>若你的站点并发比较高使用RedisMemcache能有效提升PHP并发能力</li>\
<li>若调整Session模式后网站访问异常请切换回原来的模式</li>\
<li>切换Session模式会使在线的用户会话丢失请在流量小的时候切换</li>\
</ul>\
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
</div>\
</div>";
$(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){
$('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
$('input[name="passwd"]').attr('disabled','disabled');
}
// change event
$("select[name='save_handler']").change(function() {
var type = $(this).val();
var passwd = $('input[name="passwd"]').val();
if (passwd == ""){
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
}
var ip = $('input[name="ip"]').val();
if (ip == ""){
$('input[name="ip"]').val('127.0.0.1');
}
switch (type) {
case 'redis':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('6379');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'file':
$('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled');
break;
case 'memcache':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'memcached':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
}
});
//load session stats
phpPost('get_session_count', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
<div class='clear_conter'>\
<div class='session_clear_list'>\
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
</div>\
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
$("#session_clear").html(html_var);
$('#clean_func').click(function(){
phpPost('clean_session_old', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
getSessionConfig(version);
},{ icon: rdata.status ? 1 : 2 });
});
});
});
});
}
function setSessionConfig(version){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var passwd = $('input[name="passwd"]').val();
var save_handler = $("select[name='save_handler']").val();
var data = {
ip:ip,
port:port,
passwd:passwd,
save_handler:save_handler,
};
phpPost('set_session_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//禁用函数 //禁用函数
function disableFunc(version) { function disableFunc(version) {
phpPost('get_disable_func', version,'',function(data){ phpPost('get_disable_func', version,'',function(data){

@ -1,3 +1,40 @@
<style type="text/css">
.bt-w-main{
height: 642px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form"> <div class="bt-form">
<div class='plugin_version'></div> <div class='plugin_version'></div>
<div class="bt-w-main" > <div class="bt-w-main" >
@ -13,6 +50,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p> <p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p> <p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p> <p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p> <p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p> <p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p> <p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
@ -24,6 +62,7 @@
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$.getScript( "/plugins/file?name=php&f=js/php.js", function(){ $.getScript( "/plugins/file?name=php&f=js/php.js", function(){
pluginService('php', $('.plugin_version').attr('version')); pluginService('php', $('.plugin_version').attr('version'));

@ -632,6 +632,176 @@ def getFpmStatus(version):
return mw.returnJson(True, "OK", data) return mw.returnJson(True, "OK", data)
def getSessionConf(version):
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
save_handler = re.search(rep, phpini)
if save_handler:
save_handler = save_handler.group(1)
else:
save_handler = "files"
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
save_path = re.search(reppath, phpini)
if not save_path:
save_path = re.search(memcached, phpini)
passwd = re.search(passrep, phpini)
port = ""
if passwd:
passwd = passwd.group(1)
else:
passwd = ""
if save_path:
port = save_path.group(2)
save_path = save_path.group(1)
else:
save_path = ""
data = {"save_handler": save_handler, "save_path": save_path,
"passwd": passwd, "port": port}
return mw.returnJson(True, 'ok', data)
def setSessionConf(version):
args = getArgs()
ip = args['ip']
port = args['port']
passwd = args['passwd']
save_handler = args['save_handler']
if save_handler != "file":
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址')
try:
port = int(port)
if port >= 65535 or port < 1:
return mw.returnJson(False, '请输入正确的端口号')
except:
return mw.returnJson(False, '请输入正确的端口号')
prep = r"[\~\`\/\=]"
if re.search(prep, passwd):
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
session_tmp = getServerDir() + "/tmp/session"
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
val = r'session.save_handler = ' + save_handler + '\n'
phpini = re.sub(rep, val, phpini)
if save_handler == "memcached":
if not re.search("memcached.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
if save_handler == "memcache":
if not re.search("memcache.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
if save_handler == "redis":
if not re.search("redis.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
if passwd:
passwd = "?auth=" + passwd
else:
passwd = ""
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
res = re.search(rep, phpini)
if res:
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
if save_handler == "file":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
mw.writeFile(filename, phpini)
reload(version)
return mw.returnJson(True, '设置成功!')
def getSessionCount_Origin(version):
session_tmp = getServerDir() + "/tmp/session"
d = [session_tmp]
count = 0
for i in d:
if not os.path.exists(i):
mw.execShell('mkdir -p %s' % i)
list = os.listdir(i)
for l in list:
if os.path.isdir(i + "/" + l):
l1 = os.listdir(i + "/" + l)
for ll in l1:
if "sess_" in ll:
count += 1
continue
if "sess_" in l:
count += 1
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
old_file = int(mw.execShell(s)[0].split("\n")[0])
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
old_file += int(mw.execShell(s)[0].split("\n")[0])
return {"total": count, "oldfile": old_file}
def getSessionCount(version):
data = getSessionCount_Origin(version)
return mw.returnJson(True, 'ok!', data)
def cleanSessionOld(version):
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
mw.execShell(s)
session_tmp = getServerDir() + "/tmp/session"
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
mw.execShell(s)
old_file_conf = getSessionCount_Origin(version)["oldfile"]
if old_file_conf == 0:
return mw.returnJson(True, '清理成功')
else:
return mw.returnJson(True, '清理失败')
def getDisableFunc(version): def getDisableFunc(version):
filename = getConf(version) filename = getConf(version)
if not os.path.exists(filename): if not os.path.exists(filename):
@ -794,6 +964,7 @@ def installPreInspection(version):
return 'fedora[{}]不可安装'.format(sysId) return 'fedora[{}]不可安装'.format(sysId)
return 'ok' return 'ok'
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) < 3: if len(sys.argv) < 3:
@ -847,6 +1018,14 @@ if __name__ == "__main__":
print(setFpmConfig(version)) print(setFpmConfig(version))
elif func == 'get_fpm_status': elif func == 'get_fpm_status':
print(getFpmStatus(version)) print(getFpmStatus(version))
elif func == 'get_session_conf':
print(getSessionConf(version))
elif func == 'set_session_conf':
print(setSessionConf(version))
elif func == 'get_session_count':
print(getSessionCount(version))
elif func == 'clean_session_old':
print(cleanSessionOld(version))
elif func == 'get_disable_func': elif func == 'get_disable_func':
print(getDisableFunc(version)) print(getDisableFunc(version))
elif func == 'set_disable_func': elif func == 'set_disable_func':

@ -1,14 +1,3 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function phpPost(method, version, args,callback){ function phpPost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
@ -18,7 +7,7 @@ function phpPost(method, version, args,callback){
req_data['version'] = version; req_data['version'] = version;
if (typeof(args) == 'string'){ if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args)); req_data['args'] = JSON.stringify(toArrayObject(args));
} else { } else {
req_data['args'] = JSON.stringify(args); req_data['args'] = JSON.stringify(args);
} }
@ -46,7 +35,7 @@ function phpPostCallbak(method, version, args,callback){
args['version'] = version; args['version'] = version;
if (typeof(args) == 'string'){ if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args)); req_data['args'] = JSON.stringify(toArrayObject(args));
} else { } else {
req_data['args'] = JSON.stringify(args); req_data['args'] = JSON.stringify(args);
} }
@ -194,7 +183,7 @@ function getFpmConfig(version){
"<option value='3' " + (rdata.max_children == 100 ? 'selected' : '') + ">100并发</option>" + "<option value='3' " + (rdata.max_children == 100 ? 'selected' : '') + ">100并发</option>" +
"<option value='4' " + (rdata.max_children == 200 ? 'selected' : '') + ">200并发</option>" + "<option value='4' " + (rdata.max_children == 200 ? 'selected' : '') + ">200并发</option>" +
"<option value='5' " + (rdata.max_children == 300 ? 'selected' : '') + ">300并发</option>" + "<option value='5' " + (rdata.max_children == 300 ? 'selected' : '') + ">300并发</option>" +
"<option value='6' " + (rdata.max_children == 500 ? 'selected' : '') + ">500并发</option>" "<option value='6' " + (rdata.max_children == 500 ? 'selected' : '') + ">500并发</option>";
var pms = [{ 'name': 'static', 'title': '静态' }, { 'name': 'dynamic', 'title': '动态' }]; var pms = [{ 'name': 'static', 'title': '静态' }, { 'name': 'dynamic', 'title': '动态' }];
var pmList = ''; var pmList = '';
for (var i = 0; i < pms.length; i++) { for (var i = 0; i < pms.length; i++) {
@ -340,6 +329,149 @@ function getFpmStatus(version){
}); });
} }
function getSessionConfig(version){
phpPost('get_session_conf', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
var info = rdata.save_path.split(":");
var con = "<div class='conf_p'>" +
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
"</div>\
<ul class='help-info-text c7'>\
<li>若你的站点并发比较高使用RedisMemcache能有效提升PHP并发能力</li>\
<li>若调整Session模式后网站访问异常请切换回原来的模式</li>\
<li>切换Session模式会使在线的用户会话丢失请在流量小的时候切换</li>\
</ul>\
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
</div>\
</div>";
$(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){
$('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
$('input[name="passwd"]').attr('disabled','disabled');
}
// change event
$("select[name='save_handler']").change(function() {
var type = $(this).val();
var passwd = $('input[name="passwd"]').val();
if (passwd == ""){
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
}
var ip = $('input[name="ip"]').val();
if (ip == ""){
$('input[name="ip"]').val('127.0.0.1');
}
switch (type) {
case 'redis':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('6379');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'file':
$('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled');
break;
case 'memcache':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'memcached':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
}
});
//load session stats
phpPost('get_session_count', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
<div class='clear_conter'>\
<div class='session_clear_list'>\
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
</div>\
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
$("#session_clear").html(html_var);
$('#clean_func').click(function(){
phpPost('clean_session_old', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
getSessionConfig(version);
},{ icon: rdata.status ? 1 : 2 });
});
});
});
});
}
function setSessionConfig(version){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var passwd = $('input[name="passwd"]').val();
var save_handler = $("select[name='save_handler']").val();
var data = {
ip:ip,
port:port,
passwd:passwd,
save_handler:save_handler,
};
phpPost('set_session_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//禁用函数 //禁用函数
function disableFunc(version) { function disableFunc(version) {
phpPost('get_disable_func', version,'',function(data){ phpPost('get_disable_func', version,'',function(data){

@ -1,7 +1,7 @@
daemonize yes daemonize yes
pidfile {$SERVER_PATH}/redis/redis_6379.pid pidfile {$SERVER_PATH}/redis/redis_6379.pid
bind 127.0.0.1 bind 0.0.0.0
port 6379 port 6379
requirepass admin requirepass admin

@ -125,7 +125,7 @@ def redisOp(method):
data = mw.execShell('systemctl ' + method + ' redis') data = mw.execShell('systemctl ' + method + ' redis')
if data[1] == '': if data[1] == '':
return 'ok' return 'ok'
return 'fail' return data[1]
data = mw.execShell(file + ' start') data = mw.execShell(file + ' start')
if data[1] == '': if data[1] == '':
@ -154,6 +154,10 @@ def reload():
def runInfo(): def runInfo():
s = status()
if s == 'stop':
return mw.returnJson(False, '未启动')
requirepass = "" requirepass = ""
conf = getServerDir() + '/redis.conf' conf = getServerDir() + '/redis.conf'
@ -163,9 +167,15 @@ def runInfo():
if tmp: if tmp:
requirepass = tmp.groups()[1] requirepass = tmp.groups()[1]
cmd = getServerDir() + "/bin/redis-cli info" default_ip = '0.0.0.0'
findDebian = mw.execShell('cat /etc/issue |grep Debian')
if findDebian[0] != '':
default_ip = mw.getLocalIp()
cmd = getServerDir() + "/bin/redis-cli -h " + default_ip + " info"
if requirepass != "": if requirepass != "":
cmd = getServerDir() + '/bin/redis-cli -a "' + requirepass + '" info' cmd = getServerDir() + '/bin/redis-cli -h ' + default_ip + \
' -a "' + requirepass + '" info'
data = mw.execShell(cmd)[0] data = mw.execShell(cmd)[0]
res = [ res = [

@ -5,7 +5,6 @@ After=network.target
[Service] [Service]
Type=forking Type=forking
ExecStart={$SERVER_PATH}/redis/bin/redis-server {$SERVER_PATH}/redis/redis.conf ExecStart={$SERVER_PATH}/redis/bin/redis-server {$SERVER_PATH}/redis/redis.conf
ExecStop={$SERVER_PATH}/redis/redis-cli shutdown
ExecReload=/bin/kill -USR2 $MAINPID ExecReload=/bin/kill -USR2 $MAINPID
Restart=on-failure Restart=on-failure

@ -69,6 +69,11 @@ function redisStatus(version) {
redisPost('run_info',version, {},function(data){ redisPost('run_info',version, {},function(data){
var rdata = $.parseJSON(data.data); var rdata = $.parseJSON(data.data);
// if (!rdata.status){
// layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
// return;
// }
hit = (parseInt(rdata.keyspace_hits) / (parseInt(rdata.keyspace_hits) + parseInt(rdata.keyspace_misses)) * 100).toFixed(2); hit = (parseInt(rdata.keyspace_hits) / (parseInt(rdata.keyspace_hits) + parseInt(rdata.keyspace_misses)) * 100).toFixed(2);
var con = '<div class="divtable">\ var con = '<div class="divtable">\
<table class="table table-hover table-bordered" style="width: 490px;">\ <table class="table table-hover table-bordered" style="width: 490px;">\

@ -117,7 +117,7 @@ def swapOp(method):
return 'ok' return 'ok'
return 'fail' return 'fail'
data = mw.execShell(file + ' start') data = mw.execShell(file + ' ' + method)
if data[1] == '': if data[1] == '':
return 'ok' return 'ok'
return 'fail' return 'fail'
@ -136,7 +136,7 @@ def restart():
def reload(): def reload():
return swapOp('reload') return 'ok'
def initdStatus(): def initdStatus():
@ -185,14 +185,15 @@ def changeSwap():
size = args['size'] size = args['size']
swapOp('stop') swapOp('stop')
os.system('dd if=/dev/zero of=' + getServerDir() +
'/swapfile bs=1M count=' + size)
os.system('mkswap ' + getServerDir() + '/swapfile') gsdir = getServerDir()
os.system('chmod 600 ' + getServerDir() + '/swapfile')
cmd = 'dd if=/dev/zero of=' + gsdir + '/swapfile bs=1M count=' + size
cmd += ' && mkswap ' + gsdir + '/swapfile && chmod 600 ' + gsdir + '/swapfile'
msg = mw.execShell(cmd)
swapOp('start') swapOp('start')
return mw.returnJson(True, "修改成功!") return mw.returnJson(True, "修改成功:\n" + msg[0])
if __name__ == "__main__": if __name__ == "__main__":
func = sys.argv[1] func = sys.argv[1]

@ -54,7 +54,7 @@ function modifyAuthPath() {
type: 1, type: 1,
area: "500px", area: "500px",
title: "修改安全入口", title: "修改安全入口",
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content: '<div class="bt-form bt-form pd20 pb70">\ content: '<div class="bt-form bt-form pd20 pb70">\
@ -131,7 +131,7 @@ function setPassword(a) {
type: 1, type: 1,
area: "290px", area: "290px",
title: '修改密码', title: '修改密码',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content: "<div class='bt-form pd20 pb70'>\ content: "<div class='bt-form pd20 pb70'>\
@ -187,7 +187,7 @@ function setUserName(a) {
type: 1, type: 1,
area: "290px", area: "290px",
title: '修改面板用户名', title: '修改面板用户名',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content: "<div class='bt-form pd20 pb70'>\ content: "<div class='bt-form pd20 pb70'>\
@ -238,7 +238,7 @@ function setPanelSSL(){
<input type="checkbox" id="checkSSL" /><label style="font-weight: 400;margin: 3px 5px 0px;" for="checkSSL">我已了经解详情,并愿意承担风险</label>\ <input type="checkbox" id="checkSSL" /><label style="font-weight: 400;margin: 3px 5px 0px;" for="checkSSL">我已了经解详情,并愿意承担风险</label>\
<a target="_blank" class="btlink" href="https://www.bt.cn/bbs/thread-4689-1-1.html" style="float: right;">了解详情</a>\ <a target="_blank" class="btlink" href="https://www.bt.cn/bbs/thread-4689-1-1.html" style="float: right;">了解详情</a>\
</p>'; </p>';
layer.confirm(msg,{title:'设置面板SSL',closeBtn:2,icon:3,area:'550px',cancel:function(){ layer.confirm(msg,{title:'设置面板SSL',closeBtn:1,icon:3,area:'550px',cancel:function(){
if(status == 0){ if(status == 0){
$("#panelSSL").prop("checked",false); $("#panelSSL").prop("checked",false);
} }
@ -302,7 +302,7 @@ function getPanelSSL(){
type: 1, type: 1,
area: "600px", area: "600px",
title: '自定义面板证书', title: '自定义面板证书',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content:certBody content:certBody

@ -180,7 +180,7 @@ function setControl(act, value=false){
//清理记录 //清理记录
function closeControl(){ function closeControl(){
layer.confirm('您真的清空所有监控记录吗?',{title:'清空记录',icon:3,closeBtn:2}, function() { layer.confirm('您真的清空所有监控记录吗?',{title:'清空记录',icon:3,closeBtn:1}, function() {
loadT = layer.msg('正在处理,请稍候...',{icon:16,time:0}) loadT = layer.msg('正在处理,请稍候...',{icon:16,time:0})
$.post('/system/set_control','type=del',function(rdata){ $.post('/system/set_control','type=del',function(rdata){
layer.close(loadT); layer.close(loadT);

@ -24,7 +24,7 @@ function getLogs(id){
title:lan.crontab.task_log_title, title:lan.crontab.task_log_title,
area: ['60%','500px'], area: ['60%','500px'],
shadeClose:false, shadeClose:false,
closeBtn:2, closeBtn:1,
content:'<div class="setchmod bt-form pd20 pb70">' content:'<div class="setchmod bt-form pd20 pb70">'
+'<pre id="crontab-log" style="overflow: auto; border: 0px none; line-height:23px;padding: 15px; margin: 0px; white-space: pre-wrap; height: 405px; background-color: rgb(51,51,51);color:#f1f1f1;border-radius:0px;font-family:"></pre>' +'<pre id="crontab-log" style="overflow: auto; border: 0px none; line-height:23px;padding: 15px; margin: 0px; white-space: pre-wrap; height: 405px; background-color: rgb(51,51,51);color:#f1f1f1;border-radius:0px;font-family:"></pre>'
+'<div class="bt-form-submit-btn" style="margin-top: 0px;">' +'<div class="bt-form-submit-btn" style="margin-top: 0px;">'
@ -93,7 +93,7 @@ function getCronData(page){
// 设置计划任务状态 // 设置计划任务状态
function setTaskStatus(id,status){ function setTaskStatus(id,status){
var confirm = layer.confirm(status == '0'?'计划任务暂停后将无法继续运行,您真的要停用这个计划任务吗?':'该计划任务已停用,是否要启用这个计划任务', {title:'提示',icon:3,closeBtn:2},function(index) { var confirm = layer.confirm(status == '0'?'计划任务暂停后将无法继续运行,您真的要停用这个计划任务吗?':'该计划任务已停用,是否要启用这个计划任务', {title:'提示',icon:3,closeBtn:1},function(index) {
if (index > 0) { if (index > 0) {
var loadT = layer.msg('正在设置状态,请稍后...',{icon:16,time:0,shade: [0.3, '#000']}); var loadT = layer.msg('正在设置状态,请稍后...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/crontab/set_cron_status',{id:id},function(rdata){ $.post('/crontab/set_cron_status',{id:id},function(rdata){
@ -610,7 +610,7 @@ function editTaskInfo(id){
area: ['850px','450px'], area: ['850px','450px'],
skin:'layer-create-content', skin:'layer-create-content',
shadeClose:false, shadeClose:false,
closeBtn:2, closeBtn:1,
content:'<div class="setting-con ptb20">\ content:'<div class="setting-con ptb20">\
<div class="clearfix plan ptb10">\ <div class="clearfix plan ptb10">\
<span class="typename c4 pull-left f14 text-right mr20">任务类型</span>\ <span class="typename c4 pull-left f14 text-right mr20">任务类型</span>\

@ -196,7 +196,7 @@ function recycleBin(type){
layer.open({ layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: ['80%','606px'], area: ['80%','606px'],
title: lan.files.recycle_bin_title, title: lan.files.recycle_bin_title,
content: tablehtml content: tablehtml
@ -841,7 +841,7 @@ function createFile(type, path) {
layer.open({ layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: '320px', area: '320px',
title: '新建空白文件', title: '新建空白文件',
content: '<div class="bt-form pd20 pb70">\ content: '<div class="bt-form pd20 pb70">\
@ -881,7 +881,7 @@ function createDir(type, path) {
layer.open({ layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: '320px', area: '320px',
title: '新建目录', title: '新建目录',
content: '<div class="bt-form pd20 pb70">\ content: '<div class="bt-form pd20 pb70">\
@ -981,7 +981,7 @@ function downloadFile(action){
layer.open({ layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: '500px', area: '500px',
btn:["确定","关闭"], btn:["确定","关闭"],
title: lan.files.down_title, title: lan.files.down_title,
@ -1034,7 +1034,7 @@ function reName(type, fileName) {
layer.open({ layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: '320px', area: '320px',
title: '重命名', title: '重命名',
btn:["确定","保存"], btn:["确定","保存"],
@ -1185,7 +1185,7 @@ function zip(dirName,submits) {
layer.open({ layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: '650px', area: '650px',
title: lan.files.zip_title, title: lan.files.zip_title,
content: '<div class="bt-form pd20 pb70">' content: '<div class="bt-form pd20 pb70">'
@ -1241,7 +1241,7 @@ function unZip(fileName,type) {
layer.open({ layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: '490px', area: '490px',
title: '解压文件', title: '解压文件',
content: '<div class="bt-form pd20 pb70">' content: '<div class="bt-form pd20 pb70">'
@ -1299,7 +1299,7 @@ function getImage(fileName){
var imgUrl = '/files/download?filename='+fileName; var imgUrl = '/files/download?filename='+fileName;
layer.open({ layer.open({
type:1, type:1,
closeBtn: 2, closeBtn: 1,
title:false, title:false,
area: '500px', area: '500px',
shadeClose: true, shadeClose: true,
@ -1319,7 +1319,7 @@ function uploadFiles(){
var path = $("#DirPathPlace input").val()+"/"; var path = $("#DirPathPlace input").val()+"/";
layer.open({ layer.open({
type:1, type:1,
closeBtn: 2, closeBtn: 1,
title:lan.files.up_title, title:lan.files.up_title,
area: ['500px','300px'], area: ['500px','300px'],
shadeClose:false, shadeClose:false,
@ -1364,7 +1364,7 @@ function setChmod(action,fileName){
// console.log(rdata); // console.log(rdata);
layer.open({ layer.open({
type:1, type:1,
closeBtn: 2, closeBtn: 1,
title: '设置权限['+fileName+']', title: '设置权限['+fileName+']',
area: '400px', area: '400px',
shadeClose:false, shadeClose:false,

@ -527,7 +527,7 @@ function checkUpdate() {
} }
if (rdata.status === false) { if (rdata.status === false) {
layer.confirm(rdata.msg, { title: lan.index.update_check, icon: 1, closeBtn: 2, btn: [lan.public.know, lan.public.close] }); layer.confirm(rdata.msg, { title: lan.index.update_check, icon: 1, closeBtn: 1, btn: [lan.public.know, lan.public.close] });
return; return;
} }
layer.msg(rdata.msg, { icon: 1 }); layer.msg(rdata.msg, { icon: 1 });
@ -610,7 +610,7 @@ function reBoot() {
type: 1, type: 1,
title: '重启服务器或者面板', title: '重启服务器或者面板',
area: '330px', area: '330px',
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="rebt-con"><div class="rebt-li"><a data-id="server" href="javascript:;">重启服务器</a></div><div class="rebt-li"><a data-id="panel" href="javascript:;">重启面板</a></div></div>' content: '<div class="rebt-con"><div class="rebt-li"><a data-id="server" href="javascript:;">重启服务器</a></div><div class="rebt-li"><a data-id="panel" href="javascript:;">重启面板</a></div></div>'
}); });
@ -620,7 +620,7 @@ function reBoot() {
var type = $(this).attr('data-id'); var type = $(this).attr('data-id');
switch (type) { switch (type) {
case 'panel': case 'panel':
layer.confirm('即将重启面板服务,继续吗?', { title: '重启面板服务', closeBtn: 2, icon: 3 }, function () { layer.confirm('即将重启面板服务,继续吗?', { title: '重启面板服务', closeBtn: 1, icon: 3 }, function () {
var loadT = layer.load(); var loadT = layer.load();
$.post('/system/restart','',function (rdata) { $.post('/system/restart','',function (rdata) {
layer.close(loadT); layer.close(loadT);
@ -634,7 +634,7 @@ function reBoot() {
type: 1, type: 1,
title: '安全重启服务器', title: '安全重启服务器',
area: ['500px', '280px'], area: ['500px', '280px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: "<div class='bt-form bt-window-restart'>\ content: "<div class='bt-form bt-window-restart'>\
<div class='pd15'>\ <div class='pd15'>\
@ -692,7 +692,7 @@ function reBoot() {
//修复面板 //修复面板
function repPanel() { function repPanel() {
layer.confirm(lan.index.rep_panel_msg, { title: lan.index.rep_panel_title, closeBtn: 2, icon: 3 }, function() { layer.confirm(lan.index.rep_panel_msg, { title: lan.index.rep_panel_title, closeBtn: 1, icon: 3 }, function() {
var loadT = layer.msg(lan.index.rep_panel_the, { icon: 16, time: 0, shade: [0.3, '#000'] }); var loadT = layer.msg(lan.index.rep_panel_the, { icon: 16, time: 0, shade: [0.3, '#000'] });
$.get('/system?action=RepPanel', function(rdata) { $.get('/system?action=RepPanel', function(rdata) {
layer.close(loadT); layer.close(loadT);
@ -750,7 +750,7 @@ function showDanger(num, port) {
type: 1, type: 1,
area: ['720px', '410px'], area: ['720px', '410px'],
title: '安全提醒(如你想放弃任何安全提醒通知,请删除宝塔安全登录插件)', title: '安全提醒(如你想放弃任何安全提醒通知,请删除宝塔安全登录插件)',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
content: '<div class="pd20">\ content: '<div class="pd20">\
<table class="f14 showDanger"><tbody>\ <table class="f14 showDanger"><tbody>\
@ -769,7 +769,7 @@ function showDanger(num, port) {
//加载关键数据总数 //加载关键数据总数
loadKeyDataCount(); loadKeyDataCount();
function loadKeyDataCount(){ function loadKeyDataCount(){
var plist = ['mysql', 'csvn', 'gogs']; var plist = ['mysql', 'gogs','gitea'];
for (var i = 0; i < plist.length; i++) { for (var i = 0; i < plist.length; i++) {
pname = plist[i]; pname = plist[i];
function call(pname){ function call(pname){
@ -784,7 +784,7 @@ function loadKeyDataCount(){
} }
var html = '<li class="sys-li-box col-xs-3 col-sm-3 col-md-3 col-lg-3">\ var html = '<li class="sys-li-box col-xs-3 col-sm-3 col-md-3 col-lg-3">\
<p class="name f15 c9">'+pname+'</p>\ <p class="name f15 c9">'+pname+'</p>\
<div class="val"><a class="btlink" onclick="softMain(\''+pname+'\',\''+rdata['data']['ver']+'\')">'+rdata['data']['count']+'</a></div></li>'; <div class="val"><a class="btlink" onclick="softMain(\''+pname+'\',\''+pname+'\',\''+rdata['data']['ver']+'\')">'+rdata['data']['count']+'</a></div></li>';
$('#index_overview').append(html); $('#index_overview').append(html);
},'json'); },'json');
} }

@ -204,7 +204,7 @@ function changePath(d) {
type: 1, type: 1,
area: "650px", area: "650px",
title: '选择目录', title: '选择目录',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content: "<div class='changepath'><div class='path-top'><button type='button' class='btn btn-default btn-sm' onclick='backFile()'><span class='glyphicon glyphicon-share-alt'></span></button>\ content: "<div class='changepath'><div class='path-top'><button type='button' class='btn btn-default btn-sm' onclick='backFile()'><span class='glyphicon glyphicon-share-alt'></span></button>\
@ -554,7 +554,7 @@ function onlineEditFile(k, f) {
var r = layer.open({ var r = layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: ["90%", "90%"], area: ["90%", "90%"],
title: lan.bt.edit_title+"[" + f + "]", title: lan.bt.edit_title+"[" + f + "]",
content: '<form class="bt-form pd20 pb70"><div class="line"><p style="color:red;margin-bottom:10px">'+lan.bt.edit_ps+' <select class="bt-input-text" name="encoding" style="width: 74px;position: absolute;top: 31px;right: 19px;height: 22px;z-index: 9999;border-radius: 0;">' + n + '</select></p><textarea class="mCustomScrollbar bt-input-text" id="textBody" style="width:100%;margin:0 auto;line-height: 1.8;position: relative;top: 10px;" value="" /> </div> <div class="bt-form-submit-btn" style="position:absolute; bottom:0; width:100%"> <button type="button" class="btn btn-danger btn-sm btn-editor-close">'+lan.public.close+'</button> <button id="OnlineEditFileBtn" type="button" class="btn btn-success btn-sm">'+lan.public.save+'</button> </div> </form>' content: '<form class="bt-form pd20 pb70"><div class="line"><p style="color:red;margin-bottom:10px">'+lan.bt.edit_ps+' <select class="bt-input-text" name="encoding" style="width: 74px;position: absolute;top: 31px;right: 19px;height: 22px;z-index: 9999;border-radius: 0;">' + n + '</select></p><textarea class="mCustomScrollbar bt-input-text" id="textBody" style="width:100%;margin:0 auto;line-height: 1.8;position: relative;top: 10px;" value="" /> </div> <div class="bt-form-submit-btn" style="position:absolute; bottom:0; width:100%"> <button type="button" class="btn btn-danger btn-sm btn-editor-close">'+lan.public.close+'</button> <button id="OnlineEditFileBtn" type="button" class="btn btn-success btn-sm">'+lan.public.save+'</button> </div> </form>'
@ -638,7 +638,7 @@ function safeMessage(j, h, g, f) {
type: 1, type: 1,
title: j, title: j,
area: "350px", area: "350px",
closeBtn: 2, closeBtn: 1,
shadeClose: true, shadeClose: true,
content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='vcode'>"+lan.bt.cal_msg+"<span class='text'>" + sumtext + "</span>=<input type='number' id='vcodeResult' value=''></div><div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>" content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='vcode'>"+lan.bt.cal_msg+"<span class='text'>" + sumtext + "</span>=<input type='number' id='vcodeResult' value=''></div><div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>"
}); });
@ -718,7 +718,7 @@ $(function() {
}); });
$("#dologin").click(function() { $("#dologin").click(function() {
layer.confirm('您真的要退出面板吗?', {icon:3,closeBtn: 2}, function() { layer.confirm('您真的要退出面板吗?', {icon:3,closeBtn: 1}, function() {
window.location.href = "/login?dologin=True" window.location.href = "/login?dologin=True"
}); });
return false return false
@ -1030,7 +1030,7 @@ function bindPanel(a,type,ip,btid,url,user,pw){
type: 1, type: 1,
area: "400px", area: "400px",
title: titleName, title: titleName,
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content: "<div class='bt-form pd20 pb70'>\ content: "<div class='bt-form pd20 pb70'>\
@ -1106,7 +1106,7 @@ function messageBox() {
type: 1, type: 1,
title: '消息盒子', title: '消息盒子',
area: "670px", area: "670px",
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="bt-form">\ content: '<div class="bt-form">\
<div class="bt-w-main">\ <div class="bt-w-main">\
@ -1459,7 +1459,7 @@ function webShell() {
type: 1, type: 1,
title: "本地终端", title: "本地终端",
area: ['685px','435px'], area: ['685px','435px'],
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="term-box"><div id="term"></div></div>\ content: '<div class="term-box"><div id="term"></div></div>\
<div class="shell-text-input">\ <div class="shell-text-input">\
@ -1661,7 +1661,7 @@ function pluginOpService(a, b, v) {
case "restart":d = '重启';break; case "restart":d = '重启';break;
case "reload":d = '重载';break; case "reload":d = '重载';break;
} }
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,v]), {icon:3,closeBtn: 2}, function() { layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,v]), {icon:3,closeBtn: 1}, function() {
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,v]), {icon: 16,time: 0}); var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,v]), {icon: 16,time: 0});
$.post("/plugins/run", c, function(g) { $.post("/plugins/run", c, function(g) {
layer.close(e); layer.close(e);
@ -1937,7 +1937,7 @@ function pluginOpInitD(a, _version, b) {
case "initd_install":d = '加载';break; case "initd_install":d = '加载';break;
case "initd_uninstall":d = '卸载';break; case "initd_uninstall":d = '卸载';break;
} }
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,_version]), {icon:3,closeBtn: 2}, function() { layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,_version]), {icon:3,closeBtn: 1}, function() {
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,_version]), {icon: 16,time: 0}); var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,_version]), {icon: 16,time: 0});
$.post("/plugins/run", c, function(g) { $.post("/plugins/run", c, function(g) {
layer.close(e); layer.close(e);

@ -233,7 +233,7 @@ function webAddPage(type) {
skin: 'demo-class', skin: 'demo-class',
area: '640px', area: '640px',
title: '添加网站', title: '添加网站',
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
shadeClose: false, shadeClose: false,
content: "<form class='bt-form pd20 pb70' id='addweb'>\ content: "<form class='bt-form pd20 pb70' id='addweb'>\
@ -673,7 +673,7 @@ function DomainRoot(id, name,msg) {
skin: 'demo-class', skin: 'demo-class',
area: '450px', area: '450px',
title: lan.site.domain_man, title: lan.site.domain_man,
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
shadeClose: true, shadeClose: true,
content: "<div class='divtable padding-10'>\ content: "<div class='divtable padding-10'>\
@ -869,7 +869,7 @@ function getBackup(id,name,page) {
skin: 'demo-class', skin: 'demo-class',
area: '700px', area: '700px',
title: '打包备份', title: '打包备份',
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
shadeClose: false, shadeClose: false,
content: "<div class='bt-form ptb15 mlr15' id='webBackup'>\ content: "<div class='bt-form ptb15 mlr15' id='webBackup'>\
@ -918,7 +918,7 @@ function setIndex(id){
type: 1, type: 1,
area: '500px', area: '500px',
title: lan.site.setindex, title: lan.site.setindex,
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: true, shadeClose: true,
content:"<form class='bt-form' id='SetIndex'><div class='SetIndex'>" content:"<form class='bt-form' id='SetIndex'><div class='SetIndex'>"
@ -964,7 +964,7 @@ function getDefaultSite(){
type: 1, type: 1,
area: '530px', area: '530px',
title: '设置默认站点', title: '设置默认站点',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: true, shadeClose: true,
content:'<div class="bt-form ptb15 pb70">\ content:'<div class="bt-form ptb15 pb70">\
@ -1021,7 +1021,7 @@ function webEdit(id,website,endTime,addtime){
type: 1, type: 1,
area: '640px', area: '640px',
title: '站点修改['+website+'] -- 添加时间['+addtime+']', title: '站点修改['+website+'] -- 添加时间['+addtime+']',
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
content: "<div class='bt-form'>" content: "<div class='bt-form'>"
+"<div class='bt-w-menu pull-left' style='height: 565px;'>" +"<div class='bt-w-menu pull-left' style='height: 565px;'>"
@ -1363,7 +1363,7 @@ function showRewrite(rdata){
type: 1, type: 1,
area: '500px', area: '500px',
title: '配置伪静态规则', title: '配置伪静态规则',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: true, shadeClose: true,
content:webBakHtml content:webBakHtml
@ -1430,7 +1430,7 @@ function to301(siteName, type, obj){
skin: 'demo-class', skin: 'demo-class',
area: '650px', area: '650px',
title: type == 1 ? '创建重定向' : '修改重定向[' + obj.redirectname + ']', title: type == 1 ? '创建重定向' : '修改重定向[' + obj.redirectname + ']',
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content: "<form id='form_redirect' class='divtable pd20' style='padding-bottom: 60px'>" + content: "<form id='form_redirect' class='divtable pd20' style='padding-bottom: 60px'>" +
@ -1632,7 +1632,7 @@ function toProxy(siteName, type, obj) {
type: 1, type: 1,
area: '650px', area: '650px',
title: "创建反向代理", title: "创建反向代理",
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
btn: ['提交','关闭'], btn: ['提交','关闭'],
@ -2381,7 +2381,7 @@ function setRewriteTel(act){
aindex = layer.open({ aindex = layer.open({
type: 1, type: 1,
shift: 5, shift: 5,
closeBtn: 2, closeBtn: 1,
area: '320px', //宽高 area: '320px', //宽高
title: '保存为Rewrite模板', title: '保存为Rewrite模板',
content: '<div class="bt-form pd20 pb70">\ content: '<div class="bt-form pd20 pb70">\
@ -2408,7 +2408,7 @@ function siteDefaultPage(){
type: 1, type: 1,
area: '460px', area: '460px',
title: '修改默认页', title: '修改默认页',
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
content: '<div class="changeDefault pd20">\ content: '<div class="changeDefault pd20">\
<button class="btn btn-default btn-sm mg10" style="width:188px" onclick="changeDefault(1)">默认文档</button>\ <button class="btn btn-default btn-sm mg10" style="width:188px" onclick="changeDefault(1)">默认文档</button>\
@ -2465,7 +2465,7 @@ function setClassType(){
type: 1, type: 1,
area: '350px', area: '350px',
title: '网站分类管理', title: '网站分类管理',
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
content: '<div class="bt-form edit_site_type">\ content: '<div class="bt-form edit_site_type">\
<div class="divtable mtb15" style="overflow:auto">\ <div class="divtable mtb15" style="overflow:auto">\
@ -2523,7 +2523,7 @@ function editClassType(id,name){
type: 1, type: 1,
area: '350px', area: '350px',
title: '修改分类管理【' + name + '】', title: '修改分类管理【' + name + '】',
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
content: "<form class='bt-form bt-form pd20 pb70' id='mod_pwd'>\ content: "<form class='bt-form bt-form pd20 pb70' id='mod_pwd'>\
<div class='line'>\ <div class='line'>\
@ -2563,7 +2563,7 @@ function moveClassTYpe(){
type: 1, type: 1,
area: '350px', area: '350px',
title: '设置站点分类', title: '设置站点分类',
closeBtn: 2, closeBtn: 1,
shift: 0, shift: 0,
content: '<div class="bt-form edit_site_type">\ content: '<div class="bt-form edit_site_type">\
<div class="divtable mtb15" style="overflow:auto;height:80px;">\ <div class="divtable mtb15" style="overflow:auto;height:80px;">\

@ -205,7 +205,7 @@ function addVersion(name, ver, type, obj, title, install_pre_inspection) {
type: 1, type: 1,
title: titlename + "软件安装", title: titlename + "软件安装",
area: '350px', area: '350px',
closeBtn: 2, closeBtn: 1,
shadeClose: true, shadeClose: true,
btn: ['提交','关闭'], btn: ['提交','关闭'],
content: "<div class='bt-form pd20 c6'>\ content: "<div class='bt-form pd20 c6'>\
@ -262,7 +262,7 @@ function uninstallPreInspection(name, ver, callback){
function runUninstallVersion(name, version){ function runUninstallVersion(name, version){
layer.confirm(msgTpl('您真的要卸载[{1}-{2}]吗?', [name, version]), { icon: 3, closeBtn: 2 }, function() { layer.confirm(msgTpl('您真的要卸载[{1}-{2}]吗?', [name, version]), { icon: 3, closeBtn: 1 }, function() {
var data = 'name=' + name + '&version=' + version; var data = 'name=' + name + '&version=' + version;
var loadT = layer.msg('正在处理,请稍候...', { icon: 16, time: 0, shade: [0.3, '#000'] }); var loadT = layer.msg('正在处理,请稍候...', { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/plugins/uninstall', data, function(rdata) { $.post('/plugins/uninstall', data, function(rdata) {
@ -431,7 +431,7 @@ function importPlugin(file){
type: 1, type: 1,
area: "500px", area: "500px",
title: "安装第三方插件包", title: "安装第三方插件包",
closeBtn: 2, closeBtn: 1,
shift: 5, shift: 5,
shadeClose: false, shadeClose: false,
content: '<style>\ content: '<style>\

@ -179,6 +179,22 @@ error_logs()
tail -n 100 $mw_path/logs/error.log tail -n 100 $mw_path/logs/error.log
} }
mw_update()
{
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash
}
mw_update_dev()
{
curl -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
}
mw_install_app()
{
bash $mw_path/scripts/quick/app.sh
}
case "$1" in case "$1" in
'start') mw_start;; 'start') mw_start;;
'stop') mw_stop;; 'stop') mw_stop;;
@ -194,6 +210,9 @@ case "$1" in
mw_start_task;; mw_start_task;;
'status') mw_status;; 'status') mw_status;;
'logs') error_logs;; 'logs') error_logs;;
'update') mw_update;;
'update_dev') mw_update_dev;;
'install_app') mw_install_app;;
'default') 'default')
cd $mw_path cd $mw_path
port=7200 port=7200

@ -15,8 +15,9 @@ if sys.platform != 'darwin':
chdir = os.getcwd() chdir = os.getcwd()
sys.path.append(chdir + '/class/core') sys.path.append(chdir + '/class/core')
reload(sys)
sys.setdefaultencoding('utf-8') # importlib.reload(sys)
# sys.setdefaultencoding('utf-8')
import mw import mw
print('==================================================================') print('==================================================================')

Loading…
Cancel
Save