diff --git a/BTPanel/__init__.py b/BTPanel/__init__.py index a62221b0..92fb661a 100644 --- a/BTPanel/__init__.py +++ b/BTPanel/__init__.py @@ -475,7 +475,7 @@ def config(pdata = None): if public.is_local(): data['is_local'] = 'checked' return render_template( 'config.html',data=data) import config - defs = ('get_cert_source','set_local','set_debug','get_panel_error_logs','clean_panel_error_logs','get_basic_auth_stat','set_basic_auth','get_cli_php_version','get_tmp_token','set_cli_php_version','DelOldSession', 'GetSessionCount', 'SetSessionConf', 'GetSessionConf','get_ipv6_listen','set_ipv6_status','GetApacheValue','SetApacheValue','GetNginxValue','SetNginxValue','get_token','set_token','set_admin_path','is_pro','get_php_config','get_config','SavePanelSSL','GetPanelSSL','GetPHPConf','SetPHPConf','GetPanelList','AddPanelInfo','SetPanelInfo','DelPanelInfo','ClickPanelInfo','SetPanelSSL','SetTemplates','Set502','setPassword','setUsername','setPanel','setPathInfo','setPHPMaxSize','getFpmConfig','setFpmConfig','setPHPMaxTime','syncDate','setPHPDisable','SetControl','ClosePanel','AutoUpdatePanel','SetPanelLock') + defs = ('get_php_session_path','set_php_session_path','get_cert_source','set_local','set_debug','get_panel_error_logs','clean_panel_error_logs','get_basic_auth_stat','set_basic_auth','get_cli_php_version','get_tmp_token','set_cli_php_version','DelOldSession', 'GetSessionCount', 'SetSessionConf', 'GetSessionConf','get_ipv6_listen','set_ipv6_status','GetApacheValue','SetApacheValue','GetNginxValue','SetNginxValue','get_token','set_token','set_admin_path','is_pro','get_php_config','get_config','SavePanelSSL','GetPanelSSL','GetPHPConf','SetPHPConf','GetPanelList','AddPanelInfo','SetPanelInfo','DelPanelInfo','ClickPanelInfo','SetPanelSSL','SetTemplates','Set502','setPassword','setUsername','setPanel','setPathInfo','setPHPMaxSize','getFpmConfig','setFpmConfig','setPHPMaxTime','syncDate','setPHPDisable','SetControl','ClosePanel','AutoUpdatePanel','SetPanelLock') return publicObject(config.config(),defs,None,pdata); @app.route('/ajax',methods=method_all) @@ -1103,9 +1103,16 @@ def get_input(): exludes = ['blob'] for key in request.args.keys(): data[key] = str(request.args.get(key,'')) - for key in request.form.keys(): - if key in exludes: continue - data[key] = str(request.form.get(key,'')) + try: + for key in request.form.keys(): + if key in exludes: continue + data[key] = str(request.form.get(key,'')) + except: + post = request.form.to_dict() + for key in post.keys(): + if key in exludes: continue + data[key] = str(post[key]) + if not hasattr(data,'data'): data.data = [] return data diff --git a/BTPanel/static/js/public.js b/BTPanel/static/js/public.js index b38304f1..155403a1 100644 --- a/BTPanel/static/js/public.js +++ b/BTPanel/static/js/public.js @@ -2644,13 +2644,13 @@ function web_shell() { }, 500); } }); - /* + if (socket) { socket.emit('connect_event', ''); interval = setInterval(function () { socket.emit('connect_event', ''); }, 1000); - }*/ + } term.on('data', function (data) { pdata_socket['data'] = data; diff --git a/BTPanel/static/js/site.js b/BTPanel/static/js/site.js index 60a26736..c214c655 100644 --- a/BTPanel/static/js/site.js +++ b/BTPanel/static/js/site.js @@ -1831,6 +1831,25 @@ var site = { _html.append(bt.render_help(['请根据您的程序需求选择版本', '若非必要,请尽量不要使用PHP5.2,这会降低您的服务器安全性;', 'PHP7不支持mysql扩展,默认安装mysqli以及mysql-pdo。'])); $('#webedit-con').append(_html); bt.render_clicks(_form_data.clicks); + $('#webedit-con').append('
session隔离
' + + bt.render_help(['开启后将会把session文件存放到独立文件夹独立文件夹,不与其他站点公用存储位置','若您在PHP配置中将session保存到memcache/redis等缓存器时,请不要开启此选项'])); + function get_session_status(){ + var loading = bt.load('正在获取session状态请稍后'); + bt.send('get_php_session_path','config/get_php_session_path',{id:web.id},function(tdata){ + loading.close(); + $('#session_switch').prop("checked",tdata); + }) + }; + get_session_status() + $('#session_switch').click(function() { + var val = $(this).prop('checked'); + bt.send('set_php_session_path','config/set_php_session_path',{id:web.id,act:val? 1:0},function(rdata){ + bt.msg(rdata) + }) + setTimeout(function () { + get_session_status(); + }, 500) + }) }) }) }, diff --git a/BTPanel/static/js/soft.js b/BTPanel/static/js/soft.js index edc3a5c3..82e62062 100644 --- a/BTPanel/static/js/soft.js +++ b/BTPanel/static/js/soft.js @@ -1767,6 +1767,7 @@ var soft = { ''+ (version != '52'?'':'') + (version != '73'?'':'')+ + ''+ ''+ ''+ ''+ @@ -1830,6 +1831,10 @@ var soft = { $('[name="ip"]').val('127.0.0.1'); $('[name="port"]').val('11211'); break; + case 'memcached': + $('[name="ip"]').val('127.0.0.1'); + $('[name="port"]').val('11211'); + break; } }); $('.btn_conf_save').click(function(){ @@ -1863,6 +1868,11 @@ var soft = { $('[name="port"]').attr('disabled',false); $('[name="passwd"]').attr('disabled','disabled').val(''); break; + case 'memcached': + $('[name="ip"]').attr('disabled',false); + $('[name="port"]').attr('disabled',false); + $('[name="passwd"]').attr('disabled','disabled').val(''); + break; } } }); diff --git a/class/ajax.py b/class/ajax.py index b4ace89f..040d10f1 100644 --- a/class/ajax.py +++ b/class/ajax.py @@ -23,47 +23,55 @@ def GetProcessCpuPercent(self,i,process_cpu): except: pass def GetNginxStatus(self,get): - process_cpu = {} - worker = int(public.ExecShell("ps aux|grep nginx|grep 'worker process'|wc -l")[0])-1 - workermen = int(public.ExecShell("ps aux|grep nginx|grep 'worker process'|awk '{memsum+=$6};END {print memsum}'")[0]) / 1024 - for proc in psutil.process_iter(): - if proc.name() == "nginx": - self.GetProcessCpuPercent(proc.pid,process_cpu) - time.sleep(0.5) - #取Nginx负载状态 - self.CheckStatusConf() - result = public.HttpGet('http://127.0.0.1/nginx_status') - tmp = result.split() - data = {} - if "request_time" in tmp: - data['accepts'] = tmp[8] - data['handled'] = tmp[9] - data['requests'] = tmp[10] - data['Reading'] = tmp[13] - data['Writing'] = tmp[15] - data['Waiting'] = tmp[17] - else: - data['accepts'] = tmp[9] - data['handled'] = tmp[7] - data['requests'] = tmp[8] - data['Reading'] = tmp[11] - data['Writing'] = tmp[13] - data['Waiting'] = tmp[15] - data['active'] = tmp[2] - data['worker'] = worker - data['workercpu'] = round(float(process_cpu["nginx"]),2) - data['workermen'] = "%s%s" % (int(workermen), "MB") - return data + try: + process_cpu = {} + worker = int(public.ExecShell("ps aux|grep nginx|grep 'worker process'|wc -l")[0])-1 + workermen = int(public.ExecShell("ps aux|grep nginx|grep 'worker process'|awk '{memsum+=$6};END {print memsum}'")[0]) / 1024 + for proc in psutil.process_iter(): + if proc.name() == "nginx": + self.GetProcessCpuPercent(proc.pid,process_cpu) + time.sleep(0.5) + #取Nginx负载状态 + self.CheckStatusConf() + result = public.HttpGet('http://127.0.0.1/nginx_status') + tmp = result.split() + data = {} + if "request_time" in tmp: + data['accepts'] = tmp[8] + data['handled'] = tmp[9] + data['requests'] = tmp[10] + data['Reading'] = tmp[13] + data['Writing'] = tmp[15] + data['Waiting'] = tmp[17] + else: + data['accepts'] = tmp[9] + data['handled'] = tmp[7] + data['requests'] = tmp[8] + data['Reading'] = tmp[11] + data['Writing'] = tmp[13] + data['Waiting'] = tmp[15] + data['active'] = tmp[2] + data['worker'] = worker + data['workercpu'] = round(float(process_cpu["nginx"]),2) + data['workermen'] = "%s%s" % (int(workermen), "MB") + return data + except Exception as ex: + public.WriteLog('信息获取',"Nginx负载状态获取失败: %s" % ex) + return public.returnMsg(False,'数据获取失败!') def GetPHPStatus(self,get): #取指定PHP版本的负载状态 - self.CheckStatusConf(); - version = get.version - result = public.HttpGet('http://127.0.0.1/phpfpm_'+version+'_status?json') - tmp = json.loads(result) - fTime = time.localtime(int(tmp['start time'])) - tmp['start time'] = time.strftime('%Y-%m-%d %H:%M:%S',fTime) - return tmp + try: + self.CheckStatusConf(); + version = get.version + result = public.HttpGet('http://127.0.0.1/phpfpm_'+version+'_status?json') + tmp = json.loads(result) + fTime = time.localtime(int(tmp['start time'])) + tmp['start time'] = time.strftime('%Y-%m-%d %H:%M:%S',fTime) + return tmp + except Exception as ex: + public.WriteLog('信息获取',"PHP负载状态获取失败: %s" % ex) + return public.returnMsg(False,'负载状态获取失败!') def CheckStatusConf(self): if public.get_webserver() != 'nginx': return; diff --git a/class/common.py b/class/common.py index 77cd588b..3f1aefd3 100644 --- a/class/common.py +++ b/class/common.py @@ -20,14 +20,13 @@ def __delattr__(self, key): delattr(self,key) def get_items(self): return self - class panelSetup: def init(self): ua = request.headers.get('User-Agent') if ua: ua = ua.lower(); if ua.find('spider') != -1 or ua.find('bot') != -1: return redirect('https://www.baidu.com'); - g.version = '6.9.8' + g.version = '6.9.9' g.title = public.GetConfigValue('title') g.uri = request.path session['version'] = g.version; diff --git a/class/config.py b/class/config.py index 80dbfdc7..7c00b0d5 100644 --- a/class/config.py +++ b/class/config.py @@ -617,7 +617,10 @@ def GetSessionConf(self,get): reppath = '\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n' passrep = '\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n' + memcached = '\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: @@ -656,6 +659,15 @@ def SetSessionConf(self, get): rep = 'session.save_handler\s*=\s*(.+)\r?\n' val = 'session.save_handler = ' + g + '\n' phpini = re.sub(rep, val, phpini) + if g == "memcached": + if not re.search("memcached.so", phpini): + return public.returnMsg(False, '请先安装%s扩展' % g) + rep = '\nsession.save_path\s*=\s*(.+)\r?\n' + val = '\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 g == "memcache": if not re.search("memcache.so",phpini): return public.returnMsg(False, '请先安装%s扩展' % g) @@ -692,24 +704,39 @@ def SetSessionConf(self, get): # 获取Session文件数量 def GetSessionCount(self, get): - d="/tmp" + d=["/tmp","/www/php_session"] + count = 0 - list = os.listdir(d) - for l in list: - if "sess_" in l: - count += 1 + for i in d: + if not os.path.exists(i): os.makedirs(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_conf = int(public.ExecShell(s)[0].split("\n")[0]) + old_file = int(public.ExecShell(s)[0].split("\n")[0]) + + s = "find /www/php_session -mtime +1 |grep 'sess_'|wc -l" + old_file += int(public.ExecShell(s)[0].split("\n")[0]) - return {"total":count,"oldfile":old_file_conf} + return {"total":count,"oldfile":old_file} # 删除老文件 def DelOldSession(self,get): s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f" os.system(s) - s = "find /tmp -mtime +1 |grep 'sess_'|wc -l" - old_file_conf = int(public.ExecShell(s)[0].split("\n")[0]) + s = "find /www/php_session -mtime +1 |grep 'sess_'|xargs rm -f" + os.system(s) + # s = "find /tmp -mtime +1 |grep 'sess_'|wc -l" + # old_file_conf = int(public.ExecShell(s)[0].split("\n")[0]) + old_file_conf = self.GetSessionCount(get) if old_file_conf == 0: return public.returnMsg(True, '清理成功') else: @@ -963,4 +990,59 @@ def set_local(self,get): t_str = '开启' public.writeFile(d_path,'True') public.WriteLog('面板配置','%s离线模式' % t_str) - return public.returnMsg(True,'设置成功!') \ No newline at end of file + return public.returnMsg(True,'设置成功!') + + # 修改.user.ini文件 + def _edit_user_ini(self,file,s_conf,act,session_path): + os.system("chattr -i {}".format(file)) + conf = public.readFile(file) + if act == "1": + if "session.save_path" in conf: + return False + conf = conf + ":{}/".format(session_path) + conf = conf + "\n" + s_conf + else: + rep = "\n*session.save_path(.|\n)*files" + rep1 = ":{}".format(session_path) + conf = re.sub(rep,"",conf) + conf = re.sub(rep1,"",conf) + public.writeFile(file, conf) + os.system("chattr +i {}".format(file)) + + # 设置php_session存放到独立文件夹 + def set_php_session_path(self,get): + ''' + get.id site id + get.act 0/1 + :param get: + :return: + ''' + import panelSite + site_info = public.M('sites').where('id=?', (get.id,)).field('name,path').find() + session_path = "/www/php_session/{}".format(site_info["name"]) + if os.path.exists(session_path): + os.makedirs(session_path) + run_path = panelSite.panelSite().GetSiteRunPath(get)["runPath"] + user_ini_file = "{site_path}{run_path}/.user.ini".format(site_path=site_info["path"], run_path=run_path) + conf = "session.save_path={}/\nsession.save_handler = files".format(session_path) + if get.act == "1": + if not os.path.exists(user_ini_file): + public.writeFile(user_ini_file,conf) + os.system("chattr +i {}".format(user_ini_file)) + return public.returnMsg(True,"设置成功") + self._edit_user_ini(user_ini_file,conf,get.act,session_path) + return public.returnMsg(True, "设置成功") + else: + self._edit_user_ini(user_ini_file,conf,get.act,session_path) + return public.returnMsg(True, "设置成功") + + # 获取php_session是否存放到独立文件夹 + def get_php_session_path(self,get): + import panelSite + site_info = public.M('sites').where('id=?', (get.id,)).field('name,path').find() + run_path = panelSite.panelSite().GetSiteRunPath(get)["runPath"] + user_ini_file = "{site_path}{run_path}/.user.ini".format(site_path=site_info["path"], run_path=run_path) + conf = public.readFile(user_ini_file) + if conf and "session.save_path" in conf: + return True + return False \ No newline at end of file diff --git a/class/datatool.py b/class/datatool.py index 477e7ab6..a7734c25 100644 --- a/class/datatool.py +++ b/class/datatool.py @@ -50,6 +50,7 @@ def GetdataInfo(self,get): ret3 = [] for i in tables: if i == 1049: return public.returnMsg(False,'指定数据库不存在!') + if type(i) == int: continue table = self.map_to_list(self.DB_MySQL.query("show table status from `%s` where name = '%s'" % (db_name, i[0]))) if not table: continue try: diff --git a/class/firewalls.py b/class/firewalls.py index 3df4aedc..c836d70b 100644 --- a/class/firewalls.py +++ b/class/firewalls.py @@ -210,7 +210,6 @@ def SetPing(self,get): #改远程端口 def SetSshPort(self,get): - #return public.returnMsg(False,'演示服务器,禁止此操作!'); port = get.port if int(port) < 22 or int(port) > 65535: return public.returnMsg(False,'FIREWALL_SSH_PORT_ERR'); ports = ['21','25','80','443','8080','888','8888']; @@ -224,7 +223,7 @@ def SetSshPort(self,get): public.writeFile(file,conf) if self.__isFirewalld: - self.__Obj.AddAcceptPort(port); + public.ExecShell('firewall-cmd --permanent --zone=public --add-port='+port+'/tcp') public.ExecShell('setenforce 0'); public.ExecShell('sed -i "s#SELINUX=enforcing#SELINUX=disabled#" /etc/selinux/config'); public.ExecShell("systemctl restart sshd.service") @@ -236,7 +235,8 @@ def SetSshPort(self,get): public.ExecShell("/etc/init.d/sshd restart") self.FirewallReload() - public.M('firewall').where("ps=?",('SSH远程管理服务',)).setField('port',port) + public.M('firewall').where("ps=? or ps=? or port=?",('SSH远程管理服务','SSH远程服务',port)).delete() + public.M('firewall').add('port,ps,addtime',(port,'SSH远程服务',time.strftime('%Y-%m-%d %X',time.localtime()))) public.WriteLog("TYPE_FIREWALL", "FIREWALL_SSH_PORT",(port,)) return public.returnMsg(True,'EDIT_SUCCESS') diff --git a/class/panelSite.py b/class/panelSite.py index ce656dd6..d21f3f07 100644 --- a/class/panelSite.py +++ b/class/panelSite.py @@ -2050,7 +2050,9 @@ def GetDirUserINI(self,get): data = {} data['logs'] = self.GetLogsStatus(get); data['userini'] = False; - if os.path.exists(path+'/.user.ini'): + user_ini_file = path+'/.user.ini' + user_ini_conf = public.readFile(user_ini_file) + if user_ini_conf and "open_basedir" in user_ini_conf: data['userini'] = True; data['runPath'] = self.GetSiteRunPath(get); data['pass'] = self.GetHasPwd(get); @@ -2061,7 +2063,9 @@ def DelUserInI(self,path,up = 0): useriniPath = path + '/.user.ini' if os.path.exists(useriniPath): public.ExecShell('chattr -i ' + useriniPath); - os.remove(useriniPath) + try: + os.remove(useriniPath) + except:pass for p1 in os.listdir(path): try: @@ -2081,21 +2085,36 @@ def SetDirUserINI(self,get): path = get.path runPath = self.GetRunPath(get) filename = path+runPath+'/.user.ini'; - if os.path.exists(filename): - public.ExecShell("chattr -i "+filename); - os.remove(filename) - return public.returnMsg(True, 'SITE_BASEDIR_CLOSE_SUCCESS'); - - if len(runPath) > 1: - self.DelUserInI(path + runPath); - else: - self.DelUserInI(path); - - public.writeFile(filename, 'open_basedir='+path+'/:/tmp/:/proc/'); - public.ExecShell("chattr +i "+filename); - - return public.returnMsg(True,'SITE_BASEDIR_OPEN_SUCCESS'); - + conf = public.readFile(filename) + try: + public.ExecShell("chattr -i " + filename) + # if "open_basedir" not in conf: + # return public.returnMsg(True, 'SITE_BASEDIR_CLOSE_SUCCESS'); + if conf and "open_basedir" in conf: + rep = "\n*open_basedir.*" + conf = re.sub(rep,"",conf) + if not conf: + os.remove(filename) + else: + public.writeFile(filename,conf) + public.ExecShell("chattr +i " + filename) + return public.returnMsg(True, 'SITE_BASEDIR_CLOSE_SUCCESS') + # + # if len(runPath) > 1: + # self.DelUserInI(path + runPath); + # else: + # self.DelUserInI(path); + if conf and "session.save_path" in conf: + rep = "session.save_path\s*=\s*(.*)" + s_path = re.search(rep,conf).groups(1)[0] + public.writeFile(filename, conf + '\nopen_basedir={}/:/tmp/:/proc/:{}'.format(path,s_path)) + else: + public.writeFile(filename,'open_basedir={}/:/tmp/:/proc/'.format(path)) + public.ExecShell("chattr +i " + filename) + return public.returnMsg(True,'SITE_BASEDIR_OPEN_SUCCESS'); + except Exception as e: + public.ExecShell("chattr +i " + filename) + return e # 读配置 @@ -2993,6 +3012,7 @@ def logsOpen(self,get): def GetLogsStatus(self,get): filename = public.GetConfigValue('setup_path') + '/panel/vhost/'+public.get_webserver()+'/' + get.name + '.conf'; conf = public.readFile(filename); + if not conf: return True if conf.find('#ErrorLog') != -1: return False; if conf.find("access_log /dev/null") != -1: return False; return True; @@ -3238,7 +3258,7 @@ def GetSiteRunPath(self,get): def SetSiteRunPath(self,get): siteName = public.M('sites').where('id=?',(get.id,)).getField('name'); sitePath = public.M('sites').where('id=?',(get.id,)).getField('path'); - + old_run_path = self.GetRunPath(get) #处理Nginx filename = self.setupPath + '/panel/vhost/nginx/' + siteName + '.conf' if os.path.exists(filename): @@ -3257,10 +3277,16 @@ def SetSiteRunPath(self,get): conf = conf.replace(path,sitePath + get.runPath); public.writeFile(filename,conf); - self.DelUserInI(sitePath); - get.path = sitePath; - self.SetDirUserINI(get); - + # self.DelUserInI(sitePath); + # get.path = sitePath; + # self.SetDirUserINI(get); + s_path = sitePath+old_run_path+"/.user.ini" + d_path = sitePath + get.runPath+"/.user.ini" + if s_path != d_path: + os.system("chattr -i {}".format(s_path)) + os.system("mv {} {}".format(s_path,d_path)) + os.system("chattr +i {}".format(d_path)) + public.serviceReload(); return public.returnMsg(True,'SET_SUCCESS'); diff --git a/class/public.py b/class/public.py index 45677908..7678b8cf 100644 --- a/class/public.py +++ b/class/public.py @@ -434,6 +434,8 @@ def serviceReload(): def ExecShell(cmdstring, cwd=None, timeout=None, shell=True): + a = '' + e = '' try: #通过管道执行SHELL import shlex @@ -460,7 +462,6 @@ def ExecShell(cmdstring, cwd=None, timeout=None, shell=True): except:pass except: if not a: - e = '' a = os.popen(cmdstring).read() return a,e @@ -518,7 +519,8 @@ def GetHost(port = False): host_tmp = request.headers.get('host') if not host_tmp: if request.url_root: - host_tmp = re.findall("^https?://([\w:\.-]+)",request.url_root)[0] + tmp = re.findall("(https|http)://([\w:\.-]+)",request.url_root) + if tmp: host_tmp = tmp[0] if not host_tmp: host_tmp = GetLocalIp() + ':' + readFile('data/port.pl').strip() if host_tmp.find(':') == -1: host_tmp += ':80'; diff --git a/data/licenes.pl b/data/licenes.pl new file mode 100644 index 00000000..e69de29b