mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
1. Add disk IO information to the homepage 2. Add a clear list button in the upload window 3. Optimize the background task overhead of the panel 4. Optimize the disk information caching mechanism 5. Panel Pro edition is online 6. Optimize panel resource usage 7. Optimize SSL certificate renewal 8. Fix the problem of reporting an error when the security entrance is empty 9. Fix the problem of infinite recursion when copying directories in extreme cases
1221 lines
52 KiB
Python
1221 lines
52 KiB
Python
#coding: utf-8
|
|
# +-------------------------------------------------------------------
|
|
# | 宝塔Linux面板
|
|
# +-------------------------------------------------------------------
|
|
# | Copyright (c) 2015-2016 宝塔软件(http://bt.cn) All rights reserved.
|
|
# +-------------------------------------------------------------------
|
|
# | Author: hwliang <hwl@bt.cn>
|
|
# +-------------------------------------------------------------------
|
|
from BTPanel import session,request
|
|
import public,os,json,time,apache,psutil
|
|
class ajax:
|
|
__official_url = 'https://brandnew.aapanel.com'
|
|
|
|
def GetApacheStatus(self,get):
|
|
a = apache.apache()
|
|
return a.GetApacheStatus()
|
|
|
|
def GetProcessCpuPercent(self,i,process_cpu):
|
|
try:
|
|
pp = psutil.Process(i)
|
|
if pp.name() not in process_cpu.keys():
|
|
process_cpu[pp.name()] = float(pp.cpu_percent(interval=0.01))
|
|
process_cpu[pp.name()] += float(pp.cpu_percent(interval=0.01))
|
|
except:
|
|
pass
|
|
def GetNginxStatus(self,get):
|
|
try:
|
|
if not os.path.exists('/www/server/nginx/sbin/nginx'): return public.returnMsg(False,'NGINX_NOT_INSTALL')
|
|
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.1)
|
|
#取Nginx负载状态
|
|
self.CheckStatusConf()
|
|
result = public.httpGet('http://127.0.0.1/nginx_status')
|
|
is_curl = False
|
|
tmp = []
|
|
if result:
|
|
tmp = result.split()
|
|
if len(tmp) < 15: is_curl = True
|
|
|
|
if is_curl:
|
|
result = public.ExecShell('curl http://127.0.0.1/nginx_status')[0]
|
|
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('GET_INFO','NGINX_LOAD_ERR',(ex,))
|
|
return public.returnMsg(False,'GET_DATA_ERR')
|
|
|
|
def GetPHPStatus(self,get):
|
|
#取指定PHP版本的负载状态
|
|
try:
|
|
version = get.version
|
|
uri = "/phpfpm_"+version+"_status?json"
|
|
result = public.request_php(version,uri,'')
|
|
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('GET_INFO',"PHP_LOAD_ERR",(public.get_error_info(),))
|
|
return public.returnMsg(False,'PHP_LOAD_ERR1')
|
|
|
|
def CheckStatusConf(self):
|
|
if public.get_webserver() != 'nginx': return
|
|
filename = session['setupPath'] + '/panel/vhost/nginx/phpfpm_status.conf'
|
|
if os.path.exists(filename):
|
|
if public.ReadFile(filename).find('nginx_status')!=-1: return
|
|
|
|
conf = '''server {
|
|
listen 80;
|
|
server_name 127.0.0.1;
|
|
allow 127.0.0.1;
|
|
location /nginx_status {
|
|
stub_status on;
|
|
access_log off;
|
|
}
|
|
}'''
|
|
public.writeFile(filename,conf)
|
|
public.serviceReload()
|
|
|
|
|
|
def GetTaskCount(self,get):
|
|
#取任务数量
|
|
return public.M('tasks').where("status!=?",('1',)).count()
|
|
|
|
def GetSoftList(self,get):
|
|
#取软件列表
|
|
import json,os
|
|
tmp = public.readFile('data/softList.conf')
|
|
data = json.loads(tmp)
|
|
tasks = public.M('tasks').where("status!=?",('1',)).field('status,name').select()
|
|
for i in range(len(data)):
|
|
data[i]['check'] = public.GetConfigValue('root_path')+'/'+data[i]['check']
|
|
for n in range(len(data[i]['versions'])):
|
|
#处理任务标记
|
|
isTask = '1'
|
|
for task in tasks:
|
|
tmp = public.getStrBetween('[',']',task['name'])
|
|
if not tmp:continue
|
|
tmp1 = tmp.split('-')
|
|
if data[i]['name'] == 'PHP':
|
|
if tmp1[0].lower() == data[i]['name'].lower() and tmp1[1] == data[i]['versions'][n]['version']: isTask = task['status'];
|
|
else:
|
|
if tmp1[0].lower() == data[i]['name'].lower(): isTask = task['status']
|
|
|
|
#检查安装状态
|
|
if data[i]['name'] == 'PHP':
|
|
data[i]['versions'][n]['task'] = isTask
|
|
checkFile = data[i]['check'].replace('VERSION',data[i]['versions'][n]['version'].replace('.',''))
|
|
else:
|
|
data[i]['task'] = isTask
|
|
version = public.readFile(public.GetConfigValue('root_path')+'/server/'+data[i]['name'].lower()+'/version.pl')
|
|
if not version:continue
|
|
if version.find(data[i]['versions'][n]['version']) == -1:continue
|
|
checkFile = data[i]['check']
|
|
data[i]['versions'][n]['status'] = os.path.exists(checkFile)
|
|
return data
|
|
|
|
|
|
def GetLibList(self,get):
|
|
#取插件列表
|
|
import json,os
|
|
tmp = public.readFile('data/libList.conf')
|
|
data = json.loads(tmp)
|
|
for i in range(len(data)):
|
|
data[i]['status'] = self.CheckLibInstall(data[i]['check'])
|
|
data[i]['optstr'] = self.GetLibOpt(data[i]['status'], data[i]['opt'])
|
|
return data
|
|
|
|
def CheckLibInstall(self,checks):
|
|
for cFile in checks:
|
|
if os.path.exists(cFile): return public.GetMsg("ALREADY_INSTALLED")
|
|
return public.GetMsg("NOT_INSTALL")
|
|
|
|
#取插件操作选项
|
|
def GetLibOpt(self,status,libName):
|
|
optStr = ''
|
|
if status == public.GetMsg("NOT_INSTALL"):
|
|
optStr = '<a class="link" href="javascript:InstallLib(\''+libName+'\');">'+public.GetMsg("INSTALL")+'</a>'
|
|
else:
|
|
libConfig = public.GetMsg("CONF")
|
|
if(libName == 'beta'): libConfig = public.GetMsg("CLOSE_BETA")
|
|
|
|
optStr = '<a class="link" href="javascript:SetLibConfig(\''+libName+'\');">'+libConfig+'</a> | <a class="link" href="javascript:UninstallLib(\''+libName+'\');">'+public.GetMsg("UNINSTALL")+'</a>';
|
|
return optStr
|
|
|
|
#取插件AS
|
|
def GetQiniuAS(self,get):
|
|
filename = public.GetConfigValue('setup_path') + '/panel/data/'+get.name+'As.conf'
|
|
if not os.path.exists(filename): public.writeFile(filename,'')
|
|
data = {}
|
|
data['AS'] = public.readFile(filename).split('|')
|
|
data['info'] = self.GetLibInfo(get.name)
|
|
if len(data['AS']) < 3:
|
|
data['AS'] = ['','','','']
|
|
return data
|
|
|
|
|
|
#设置插件AS
|
|
def SetQiniuAS(self,get):
|
|
info = self.GetLibInfo(get.name)
|
|
filename = public.GetConfigValue('setup_path') + '/panel/data/'+get.name+'As.conf'
|
|
conf = get.access_key.strip() + '|' + get.secret_key.strip() + '|' + get.bucket_name.strip() + '|' + get.bucket_domain.strip()
|
|
public.writeFile(filename,conf)
|
|
public.ExecShell("chmod 600 " + filename)
|
|
result = public.ExecShell(public.get_python_bin() + " " + public.GetConfigValue('setup_path') + "/panel/script/backup_"+get.name+".py list")
|
|
|
|
if result[0].find("ERROR:") == -1:
|
|
public.WriteLog("PLUG_MAM","SET_PLUG[" +info['name']+ "]AS!")
|
|
return public.returnMsg(True, 'SET_SUCCESS')
|
|
return public.returnMsg(False,'AK_SK_CONNECT_ERROR',(info['name'],))
|
|
|
|
#设置内测
|
|
def SetBeta(self,get):
|
|
data = {}
|
|
data['username'] = get.bbs_name
|
|
data['qq'] = get.qq
|
|
data['email'] = get.email
|
|
result = public.httpPost(public.GetConfigValue('home') + '/Api/LinuxBeta',data)
|
|
import json
|
|
data = json.loads(result)
|
|
if data['status']:
|
|
public.writeFile('data/beta.pl',get.bbs_name + '|' + get.qq + '|' + get.email)
|
|
return data
|
|
#取内测资格状态
|
|
def GetBetaStatus(self,get):
|
|
try:
|
|
return public.readFile('data/beta.pl').strip()
|
|
except:
|
|
return 'False'
|
|
|
|
|
|
#获取指定插件信息
|
|
def GetLibInfo(self,name):
|
|
import json
|
|
tmp = public.readFile('data/libList.conf')
|
|
data = json.loads(tmp)
|
|
for lib in data:
|
|
if name == lib['opt']: return lib
|
|
return False
|
|
|
|
#获取文件列表
|
|
def GetQiniuFileList(self,get):
|
|
try:
|
|
import json
|
|
result = public.ExecShell(public.get_python_bin() + " " + public.GetConfigValue('setup_path') + "/panel/script/backup_"+get.name+".py list")
|
|
return json.loads(result[0])
|
|
except:
|
|
return public.returnMsg(False, 'GET_QINIU_FILE_LIST')
|
|
|
|
|
|
|
|
#取网络连接列表
|
|
def GetNetWorkList(self,get):
|
|
import psutil
|
|
netstats = psutil.net_connections()
|
|
networkList = []
|
|
for netstat in netstats:
|
|
tmp = {}
|
|
if netstat.type == 1:
|
|
tmp['type'] = 'tcp'
|
|
else:
|
|
tmp['type'] = 'udp'
|
|
tmp['family'] = netstat.family
|
|
tmp['laddr'] = netstat.laddr
|
|
tmp['raddr'] = netstat.raddr
|
|
tmp['status'] = netstat.status
|
|
p = psutil.Process(netstat.pid)
|
|
tmp['process'] = p.name()
|
|
tmp['pid'] = netstat.pid
|
|
networkList.append(tmp)
|
|
del(p)
|
|
del(tmp)
|
|
networkList = sorted(networkList, key=lambda x : x['status'], reverse=True)
|
|
return networkList
|
|
|
|
#取进程列表
|
|
def GetProcessList(self,get):
|
|
import psutil,pwd
|
|
Pids = psutil.pids()
|
|
|
|
processList = []
|
|
for pid in Pids:
|
|
try:
|
|
tmp = {}
|
|
p = psutil.Process(pid)
|
|
if p.exe() == "": continue
|
|
|
|
tmp['name'] = p.name(); #进程名称
|
|
if self.GoToProcess(tmp['name']): continue
|
|
|
|
|
|
tmp['pid'] = pid #进程标识
|
|
tmp['status'] = p.status() #进程状态
|
|
tmp['user'] = p.username() #执行用户
|
|
cputimes = p.cpu_times()
|
|
tmp['cpu_percent'] = p.cpu_percent(0.1)
|
|
tmp['cpu_times'] = cputimes.user #进程占用的CPU时间
|
|
tmp['memory_percent'] = round(p.memory_percent(),3) #进程占用的内存比例
|
|
pio = p.io_counters()
|
|
tmp['io_write_bytes'] = pio.write_bytes #进程总共写入字节数
|
|
tmp['io_read_bytes'] = pio.read_bytes #进程总共读取字节数
|
|
tmp['threads'] = p.num_threads() #进程总线程数
|
|
|
|
processList.append(tmp)
|
|
del(p)
|
|
del(tmp)
|
|
except:
|
|
continue
|
|
import operator
|
|
processList = sorted(processList, key=lambda x : x['memory_percent'], reverse=True)
|
|
processList = sorted(processList, key=lambda x : x['cpu_times'], reverse=True)
|
|
return processList
|
|
|
|
#结束指定进程
|
|
def KillProcess(self,get):
|
|
#return public.returnMsg(False,'演示服务器,禁止此操作!');
|
|
import psutil
|
|
p = psutil.Process(int(get.pid))
|
|
name = p.name()
|
|
if name == 'python': return public.returnMsg(False,'KILL_PROCESS_ERR')
|
|
|
|
p.kill()
|
|
public.WriteLog('TYPE_PROCESS','KILL_PROCESS',(get.pid,name))
|
|
return public.returnMsg(True,'KILL_PROCESS',(get.pid,name))
|
|
|
|
def GoToProcess(self,name):
|
|
ps = ['sftp-server','login','nm-dispatcher','irqbalance','qmgr','wpa_supplicant','lvmetad','auditd','master','dbus-daemon','tapdisk','sshd','init','ksoftirqd','kworker','kmpathd','kmpath_handlerd','python','kdmflush','bioset','crond','kthreadd','migration','rcu_sched','kjournald','iptables','systemd','network','dhclient','systemd-journald','NetworkManager','systemd-logind','systemd-udevd','polkitd','tuned','rsyslogd']
|
|
|
|
for key in ps:
|
|
if key == name: return True
|
|
|
|
return False
|
|
|
|
|
|
def GetNetWorkIo(self,get):
|
|
#取指定时间段的网络Io
|
|
data = public.M('network').dbfile('system').where("addtime>=? AND addtime<=?",(get.start,get.end)).field('id,up,down,total_up,total_down,down_packets,up_packets,addtime').order('id asc').select()
|
|
return self.ToAddtime(data,None)
|
|
|
|
def GetDiskIo(self,get):
|
|
#取指定时间段的磁盘Io
|
|
data = public.M('diskio').dbfile('system').where("addtime>=? AND addtime<=?",(get.start,get.end)).field('id,read_count,write_count,read_bytes,write_bytes,read_time,write_time,addtime').order('id asc').select()
|
|
return self.ToAddtime(data)
|
|
def GetCpuIo(self,get):
|
|
#取指定时间段的CpuIo
|
|
data = public.M('cpuio').dbfile('system').where("addtime>=? AND addtime<=?",(get.start,get.end)).field('id,pro,mem,addtime').order('id asc').select()
|
|
return self.ToAddtime(data,True)
|
|
|
|
def get_load_average(self,get):
|
|
data = public.M('load_average').dbfile('system').where("addtime>=? AND addtime<=?",(get.start,get.end)).field('id,pro,one,five,fifteen,addtime').order('id asc').select()
|
|
return self.ToAddtime(data)
|
|
|
|
|
|
def ToAddtime(self,data,tomem = False):
|
|
import time
|
|
#格式化addtime列
|
|
|
|
if tomem:
|
|
import psutil
|
|
mPre = (psutil.virtual_memory().total / 1024 / 1024) / 100
|
|
length = len(data)
|
|
he = 1
|
|
if length > 100: he = 1
|
|
if length > 1000: he = 3
|
|
if length > 10000: he = 15
|
|
if he == 1:
|
|
for i in range(length):
|
|
data[i]['addtime'] = time.strftime('%m/%d %H:%M',time.localtime(float(data[i]['addtime'])))
|
|
if tomem and data[i]['mem'] > 100: data[i]['mem'] = data[i]['mem'] / mPre
|
|
if tomem in [None]:
|
|
if type(data[i]['down_packets']) == str:
|
|
data[i]['down_packets'] = json.loads(data[i]['down_packets'])
|
|
data[i]['up_packets'] = json.loads(data[i]['up_packets'])
|
|
return data
|
|
else:
|
|
count = 0
|
|
tmp = []
|
|
for value in data:
|
|
if count < he:
|
|
count += 1
|
|
continue
|
|
value['addtime'] = time.strftime('%m/%d %H:%M',time.localtime(float(value['addtime'])))
|
|
if tomem and value['mem'] > 100: value['mem'] = value['mem'] / mPre
|
|
if tomem in [None]:
|
|
if type(value['down_packets']) == str:
|
|
value['down_packets'] = json.loads(value['down_packets'])
|
|
value['up_packets'] = json.loads(value['up_packets'])
|
|
tmp.append(value)
|
|
count = 0
|
|
return tmp
|
|
|
|
def GetInstalleds(self,softlist):
|
|
softs = ''
|
|
for soft in softlist['data']:
|
|
try:
|
|
for v in soft['versions']:
|
|
if v['status']: softs += soft['name'] + '-' + v['version'] + '|'
|
|
except:
|
|
pass
|
|
return softs
|
|
|
|
|
|
|
|
#获取SSH爆破次数
|
|
def get_ssh_intrusion(self):
|
|
fp = open('/var/log/secure','rb')
|
|
l = fp.readline()
|
|
intrusion_total = 0
|
|
while l:
|
|
if l.find('Failed password for root') != -1: intrusion_total += 1
|
|
l = fp.readline()
|
|
fp.close()
|
|
return intrusion_total
|
|
|
|
#申请内测版
|
|
def apple_beta(self,get):
|
|
try:
|
|
# userInfo = json.loads(public.ReadFile('data/userInfo.json'))
|
|
# p_data = {}
|
|
# p_data['uid'] = userInfo['uid']
|
|
# p_data['access_key'] = userInfo['access_key']
|
|
# p_data['username'] = userInfo['username']
|
|
# result = public.HttpPost(public.GetConfigValue('home') + '/api/panel/apple_beta',p_data,5)
|
|
public.writeFile('/www/server/panel/data/is_beta.pl','true')
|
|
try:
|
|
return {'status': True, 'msg': "Successful application!"}
|
|
except: return public.returnMsg(False,'AJAX_CONN_ERR')
|
|
except: return public.returnMsg(False,'AJAX_USER_BINDING_ERR')
|
|
|
|
def to_not_beta(self,get):
|
|
try:
|
|
# userInfo = json.loads(public.ReadFile('data/userInfo.json'))
|
|
# p_data = {}
|
|
# p_data['uid'] = userInfo['uid']
|
|
# p_data['access_key'] = userInfo['access_key']
|
|
# p_data['username'] = userInfo['username']
|
|
# result = public.HttpPost(public.GetConfigValue('home') + '/api/panel/to_not_beta',p_data,5)
|
|
try:
|
|
beta_file = '/www/server/panel/data/is_beta.pl'
|
|
if os.path.exists(beta_file):
|
|
os.remove(beta_file)
|
|
return {"status": True, "msg": "Successful application!"}
|
|
except: return public.returnMsg(False,'AJAX_CONN_ERR')
|
|
except: return public.returnMsg(False,'AJAX_USER_BINDING_ERR')
|
|
|
|
def to_beta(self):
|
|
try:
|
|
userInfo = json.loads(public.ReadFile('data/userInfo.json'))
|
|
p_data = {}
|
|
p_data['uid'] = userInfo['uid']
|
|
p_data['access_key'] = userInfo['access_key']
|
|
p_data['username'] = userInfo['username']
|
|
public.HttpPost(public.GetConfigValue('home') + '/api/panel/to_beta',p_data,5)
|
|
except: pass
|
|
|
|
def get_uid(self):
|
|
try:
|
|
userInfo = json.loads(public.ReadFile('data/userInfo.json'))
|
|
return userInfo['uid']
|
|
except: return 0
|
|
|
|
#获取最新的5条测试版更新日志
|
|
def get_beta_logs(self,get):
|
|
try:
|
|
# data = json.loads(public.HttpGet('https://console.aapanel.com/api/panel/get_beta_logs_en'))
|
|
data = json.loads(public.HttpGet('{}/api/panel/getBetaVersionLogs'.format(self.__official_url)))
|
|
return data
|
|
except:
|
|
return public.returnMsg(False,'AJAX_CONN_ERR')
|
|
|
|
def get_other_info(self):
|
|
other = {}
|
|
other['ds'] = []
|
|
ds = public.M('domain').field('name').select()
|
|
for d in ds:
|
|
other['ds'].append(d['name'])
|
|
return ','.join(other['ds'])
|
|
|
|
|
|
|
|
|
|
def UpdatePanel(self,get):
|
|
try:
|
|
if not public.IsRestart(): return public.returnMsg(False,'EXEC_ERR_TASK')
|
|
import json
|
|
conf_status = public.M('config').where("id=?",('1',)).field('status').find()
|
|
if int(session['config']['status']) == 0 and int(conf_status['status']) == 0:
|
|
# public.HttpGet('{}/api/setupCount/setupPanel?type=Linux'.format(self.__official_url))
|
|
public.arequests('get', '{}/api/setupCount/setupPanel?type=Linux'.format(self.__official_url))
|
|
|
|
public.M('config').where("id=?",('1',)).setField('status',1)
|
|
|
|
#取回远程版本信息
|
|
if 'updateInfo' in session and hasattr(get,'check') == False:
|
|
updateInfo = session['updateInfo']
|
|
else:
|
|
logs = public.get_debug_log()
|
|
import psutil,system,sys
|
|
mem = psutil.virtual_memory()
|
|
import panelPlugin
|
|
mplugin = panelPlugin.panelPlugin()
|
|
|
|
mplugin.ROWS = 10000
|
|
panelsys = system.system()
|
|
data = {}
|
|
data['ds'] = ''#self.get_other_info()
|
|
data['sites'] = str(public.M('sites').count())
|
|
data['ftps'] = str(public.M('ftps').count())
|
|
data['databases'] = str(public.M('databases').count())
|
|
data['system'] = panelsys.GetSystemVersion() + '|' + str(mem.total / 1024 / 1024) + 'MB|' + str(public.getCpuType()) + '*' + str(psutil.cpu_count()) + '|' + str(public.get_webserver()) + '|' +session['version']
|
|
data['system'] += '||'+self.GetInstalleds(mplugin.getPluginList(None))
|
|
data['logs'] = logs
|
|
data['client'] = request.headers.get('User-Agent')
|
|
data['oem'] = ''
|
|
data['intrusion'] = 0
|
|
data['uid'] = self.get_uid()
|
|
#msg = public.getMsg('PANEL_UPDATE_MSG');
|
|
data['o'] = public.get_oem_name()
|
|
sUrl = '{}/api/panel/updateLinuxEn'.format(self.__official_url)
|
|
updateInfo = json.loads(public.httpPost(sUrl,data))
|
|
if not updateInfo: return public.returnMsg(False,"CONNECT_ERR")
|
|
#updateInfo['msg'] = msg;
|
|
if os.path.exists('/www/server/panel/data/is_beta.pl'):
|
|
updateInfo['is_beta'] = 1
|
|
session['updateInfo'] = updateInfo
|
|
|
|
#检查是否需要升级
|
|
if updateInfo['is_beta'] == 1:
|
|
if updateInfo['beta']['version'] ==session['version']: return public.returnMsg(False,updateInfo)
|
|
else:
|
|
if updateInfo['version'] ==session['version']: return public.returnMsg(False,updateInfo)
|
|
|
|
|
|
#是否执行升级程序
|
|
if(updateInfo['force'] == True or hasattr(get,'toUpdate') == True or os.path.exists('data/autoUpdate.pl') == True):
|
|
if updateInfo['is_beta'] == 1: updateInfo['version'] = updateInfo['beta']['version']
|
|
setupPath = public.GetConfigValue('setup_path')
|
|
uptype = 'update'
|
|
httpUrl = public.get_url()
|
|
if httpUrl: updateInfo['downUrl'] = httpUrl + '/install/' + uptype + '/LinuxPanel_EN-' + updateInfo['version'] + '.zip'
|
|
public.downloadFile(updateInfo['downUrl'],'panel.zip')
|
|
if os.path.getsize('panel.zip') < 1048576: return public.returnMsg(False,"PANEL_UPDATE_ERR_DOWN")
|
|
public.ExecShell('unzip -o panel.zip -d ' + setupPath + '/')
|
|
import compileall
|
|
if os.path.exists('/www/server/panel/runserver.py'): public.ExecShell('rm -f /www/server/panel/*.pyc')
|
|
if os.path.exists('/www/server/panel/class/common.py'): public.ExecShell('rm -f /www/server/panel/class/*.pyc')
|
|
|
|
if os.path.exists('panel.zip'):os.remove("panel.zip")
|
|
session['version'] = updateInfo['version']
|
|
if 'getCloudPlugin' in session: del(session['getCloudPlugin'])
|
|
if updateInfo['is_beta'] == 1: self.to_beta()
|
|
public.ExecShell("/etc/init.d/bt start")
|
|
public.writeFile('data/restart.pl','True')
|
|
return public.returnMsg(True,'PANEL_UPDATE',(updateInfo['version'],))
|
|
|
|
#输出新版本信息
|
|
data = {
|
|
'status' : True,
|
|
'version': updateInfo['version'],
|
|
'updateMsg' : updateInfo['updateMsg']
|
|
}
|
|
|
|
public.ExecShell('rm -rf /www/server/phpinfo/*')
|
|
return public.returnMsg(True,updateInfo)
|
|
except Exception as ex:
|
|
return public.get_error_info()
|
|
return public.returnMsg(False,"CONNECT_ERR")
|
|
|
|
#检查是否安装任何
|
|
def CheckInstalled(self,get):
|
|
checks = ['nginx','apache','php','pure-ftpd','mysql']
|
|
import os
|
|
for name in checks:
|
|
filename = public.GetConfigValue('root_path') + "/server/" + name
|
|
if os.path.exists(filename): return True
|
|
return False
|
|
|
|
|
|
#取已安装软件列表
|
|
def GetInstalled(self,get):
|
|
import system
|
|
data = system.system().GetConcifInfo()
|
|
return data
|
|
|
|
#取PHP配置
|
|
def GetPHPConfig(self,get):
|
|
import re,json
|
|
filename = public.GetConfigValue('setup_path') + '/php/' + get.version + '/etc/php.ini'
|
|
if public.get_webserver() == 'openlitespeed':
|
|
filename = '/usr/local/lsws/lsphp{}/etc/php/{}.{}/litespeed/php.ini'.format(get.version,get.version[0],get.version[1])
|
|
if os.path.exists('/etc/redhat-release'):
|
|
filename = '/usr/local/lsws/lsphp' + get.version + '/etc/php.ini'
|
|
if not os.path.exists(filename): return public.returnMsg(False,'PHP_NOT_EXISTS')
|
|
phpini = public.readFile(filename)
|
|
data = {}
|
|
rep = "disable_functions\s*=\s{0,1}(.*)\n"
|
|
tmp = re.search(rep,phpini).groups()
|
|
data['disable_functions'] = tmp[0]
|
|
|
|
rep = "upload_max_filesize\s*=\s*([0-9]+)(M|m|K|k)"
|
|
tmp = re.search(rep,phpini).groups()
|
|
data['max'] = tmp[0]
|
|
|
|
rep = u"\n;*\s*cgi\.fix_pathinfo\s*=\s*([0-9]+)\s*\n"
|
|
tmp = re.search(rep,phpini).groups()
|
|
if tmp[0] == '0':
|
|
data['pathinfo'] = False
|
|
else:
|
|
data['pathinfo'] = True
|
|
self.getCloudPHPExt(get)
|
|
phplib = json.loads(public.readFile('data/phplib.conf'))
|
|
libs = []
|
|
tasks = public.M('tasks').where("status!=?",('1',)).field('status,name').select()
|
|
phpini_ols = None
|
|
for lib in phplib:
|
|
lib['task'] = '1'
|
|
for task in tasks:
|
|
tmp = public.getStrBetween('[',']',task['name'])
|
|
if not tmp:continue
|
|
tmp1 = tmp.split('-')
|
|
if tmp1[0].lower() == lib['name'].lower():
|
|
lib['task'] = task['status']
|
|
lib['phpversions'] = []
|
|
lib['phpversions'].append(tmp1[1])
|
|
if public.get_webserver() == 'openlitespeed':
|
|
lib['status'] = False
|
|
get.php_version = "{}.{}".format(get.version[0],get.version[1])
|
|
if not phpini_ols:
|
|
phpini_ols = self.php_info(get)['phpinfo']['modules'].lower()
|
|
phpini_ols = phpini_ols.split()
|
|
for i in phpini_ols:
|
|
if lib['check'][:-3].lower() == i :
|
|
lib['status'] = True
|
|
break
|
|
if "ioncube" in lib['check'][:-3].lower() and "ioncube" == i:
|
|
lib['status'] = True
|
|
break
|
|
else:
|
|
if phpini.find(lib['check']) == -1:
|
|
lib['status'] = False
|
|
else:
|
|
lib['status'] = True
|
|
|
|
libs.append(lib)
|
|
|
|
data['libs'] = libs
|
|
return data
|
|
|
|
#获取PHP扩展
|
|
def getCloudPHPExt(self,get):
|
|
try:
|
|
self._process_chinese_ext_description()
|
|
if 'php_ext' in session: return True
|
|
if not self._get_cloud_phplib():
|
|
return False
|
|
session['php_ext'] = True
|
|
return True
|
|
except:
|
|
return False
|
|
|
|
# 处理PHP插件变描述中文
|
|
def _process_chinese_ext_description(self):
|
|
chinese = None
|
|
phplib = json.loads(public.readFile('data/phplib.conf'))
|
|
for p in phplib:
|
|
if "缓存器" in p['type']:
|
|
chinese = True
|
|
break
|
|
if chinese:
|
|
self._get_cloud_phplib()
|
|
|
|
# 下载云端php扩展配置
|
|
def _get_cloud_phplib(self):
|
|
if not session.get('download_url'): session['download_url'] = 'http://download.bt.cn'
|
|
download_url = session['download_url'] + '/install/lib/phplib_en.json'
|
|
tstr = public.httpGet(download_url)
|
|
data = json.loads(tstr)
|
|
if not data: return False
|
|
public.writeFile('data/phplib.conf', json.dumps(data))
|
|
return True
|
|
|
|
#取PHPINFO信息
|
|
def GetPHPInfo(self,get):
|
|
if public.get_webserver() == "openlitespeed":
|
|
shell_str = "/usr/local/lsws/lsphp{}/bin/php -i".format(get.version)
|
|
return public.ExecShell(shell_str)[0]
|
|
sPath = '/www/server/phpinfo'
|
|
if os.path.exists(sPath):
|
|
public.ExecShell("rm -rf " + sPath)
|
|
p_file = '/dev/shm/phpinfo.php'
|
|
public.writeFile(p_file,'<?php phpinfo(); ?>')
|
|
phpinfo = public.request_php(get.version,'/phpinfo.php','/dev/shm')
|
|
if os.path.exists(p_file): os.remove(p_file)
|
|
return phpinfo.decode()
|
|
|
|
#清理日志
|
|
def delClose(self,get):
|
|
if not 'uid' in session: session['uid'] = 1
|
|
if session['uid'] != 1: return public.returnMsg(False,'PERMISSION_DENIED')
|
|
if 'tmp_login_id' in session:
|
|
return public.returnMsg(False,'PERMISSION_DENIED')
|
|
|
|
public.M('logs').where('id>?',(0,)).delete()
|
|
public.WriteLog('TYPE_CONFIG','LOG_CLOSE')
|
|
return public.returnMsg(True,'LOG_CLOSE')
|
|
|
|
def __get_webserver_conffile(self):
|
|
webserver = public.get_webserver()
|
|
if webserver == 'nginx':
|
|
filename = public.GetConfigValue('setup_path') + '/nginx/conf/nginx.conf'
|
|
elif webserver == 'openlitespeed':
|
|
filename = public.GetConfigValue('setup_path') + "/panel/vhost/openlitespeed/detail/phpmyadmin.conf"
|
|
else:
|
|
filename = public.GetConfigValue('setup_path') + '/apache/conf/extra/httpd-vhosts.conf'
|
|
return filename
|
|
|
|
# 获取phpmyadmin ssl配置
|
|
def get_phpmyadmin_conf(self):
|
|
if public.get_webserver() == "nginx":
|
|
conf_file = "/www/server/panel/vhost/nginx/phpmyadmin.conf"
|
|
rep = r"listen\s*(\d+)"
|
|
else:
|
|
conf_file = "/www/server/panel/vhost/apache/phpmyadmin.conf"
|
|
rep = r"Listen\s*(\d+)"
|
|
return {"conf_file":conf_file,"rep":rep}
|
|
|
|
# 设置phpmyadmin路径
|
|
def set_phpmyadmin_session(self):
|
|
import re
|
|
conf_file = self.get_phpmyadmin_conf()
|
|
conf = public.readFile(conf_file["conf_file"])
|
|
rep = conf_file["rep"]
|
|
if conf:
|
|
port = re.search(rep,conf).group(1)
|
|
if session['phpmyadminDir']:
|
|
path = session['phpmyadminDir'].split("/")[-1]
|
|
ip = public.GetHost()
|
|
session['phpmyadminDir'] = "https://{}:{}/{}".format(ip, port, path)
|
|
|
|
# 获取phpmyadmin ssl状态
|
|
def get_phpmyadmin_ssl(self,get):
|
|
import re
|
|
conf_file = self.get_phpmyadmin_conf()
|
|
conf = public.readFile(conf_file["conf_file"])
|
|
rep = conf_file["rep"]
|
|
if conf:
|
|
port = re.search(rep, conf).group(1)
|
|
return {"status":True,"port":port}
|
|
return {"status":False,"port":""}
|
|
|
|
# 修改php ssl端口
|
|
def change_phpmyadmin_ssl_port(self,get):
|
|
if public.get_webserver() == "openlitespeed":
|
|
return public.returnMsg(False, 'NOT_SUPPORT_OLS')
|
|
import re
|
|
try:
|
|
port = int(get.port)
|
|
if 1 > port > 65535:
|
|
return public.returnMsg(False, 'PORT_CHECK_RANGE')
|
|
except:
|
|
return public.returnMsg(False, 'PORT_FORMAT_ERR')
|
|
for i in ["nginx","apache"]:
|
|
file = "/www/server/panel/vhost/{}/phpmyadmin.conf".format(i)
|
|
conf = public.readFile(file)
|
|
if not conf:
|
|
return public.returnMsg(False,"PHPMYADMIN_SSL_ERR",(i,))
|
|
rulePort = ['80', '443', '21', '20', '8080', '8081', '8089', '11211', '6379']
|
|
if get.port in rulePort:
|
|
return public.returnMsg(False, 'AJAX_PHPMYADMIN_PORT_ERR')
|
|
if i == "nginx":
|
|
if not os.path.exists("/www/server/panel/vhost/apache/phpmyadmin.conf"):
|
|
return public.returnMsg(False, "PHPMYADMIN_SSL_ERR1")
|
|
rep = "listen\s*([0-9]+)\s*.*;"
|
|
oldPort = re.search(rep, conf)
|
|
if not oldPort:
|
|
return public.returnMsg(False, 'PHPMYADMIN_SSL_ERR2')
|
|
oldPort = oldPort.groups()[0]
|
|
conf = re.sub(rep, 'listen ' + get.port + ' ssl;', conf)
|
|
else:
|
|
rep = "Listen\s*([0-9]+)\s*\n"
|
|
oldPort = re.search(rep, conf)
|
|
if not oldPort:
|
|
return public.returnMsg(False, 'PHPMYADMIN_SSL_ERR3')
|
|
oldPort = oldPort.groups()[0]
|
|
conf = re.sub(rep, "Listen " + get.port + "\n", conf, 1)
|
|
rep = "VirtualHost\s*\*:[0-9]+"
|
|
conf = re.sub(rep, "VirtualHost *:" + get.port, conf, 1)
|
|
if oldPort == get.port: return public.returnMsg(False, 'SOFT_PHPVERSION_ERR_PORT')
|
|
public.writeFile(file, conf)
|
|
public.serviceReload()
|
|
if i=="apache":
|
|
import firewalls
|
|
get.ps = public.getMsg('SOFT_PHPVERSION_PS')
|
|
fw = firewalls.firewalls()
|
|
fw.AddAcceptPort(get)
|
|
public.serviceReload()
|
|
public.WriteLog('TYPE_SOFT', 'SOFT_PHPMYADMIN_PORT', (get.port,))
|
|
get.id = public.M('firewall').where('port=?', (oldPort,)).getField('id')
|
|
get.port = oldPort
|
|
fw.DelAcceptPort(get)
|
|
return public.returnMsg(True, 'SET_PORT_SUCCESS')
|
|
|
|
def _get_phpmyadmin_auth(self):
|
|
import re
|
|
nginx_conf = '/www/server/nginx/conf/nginx.conf'
|
|
reg = '#AUTH_START(.|\n)*#AUTH_END'
|
|
if os.path.exists(nginx_conf):
|
|
nginx_conf = public.readFile(nginx_conf)
|
|
auth_tmp = re.search(reg, nginx_conf)
|
|
if auth_tmp:
|
|
return True
|
|
apache_conf = '/www/server/apache/conf/extra/httpd-vhosts.conf'
|
|
if os.path.exists(apache_conf):
|
|
apache_conf = public.readFile(apache_conf)
|
|
auth_tmp = re.search(reg, apache_conf)
|
|
if auth_tmp:
|
|
return True
|
|
|
|
# 设置phpmyadmin ssl
|
|
def set_phpmyadmin_ssl(self,get):
|
|
if public.get_webserver() == "openlitespeed":
|
|
return public.returnMsg(False, 'NOT_SUPPORT_OLS')
|
|
if not os.path.exists("/www/server/panel/ssl/certificate.pem"):
|
|
return public.returnMsg(False,'PHPMYADMIN_SSL_ERR4')
|
|
if get.v == "1":
|
|
# 获取auth信息
|
|
auth = ""
|
|
if self._get_phpmyadmin_auth():
|
|
auth = """
|
|
#AUTH_START
|
|
auth_basic "Authorization";
|
|
auth_basic_user_file /www/server/pass/phpmyadmin.pass;
|
|
#AUTH_END
|
|
"""
|
|
# nginx配置文件
|
|
ssl_conf = """server
|
|
{
|
|
listen 887 ssl;
|
|
server_name phpmyadmin;
|
|
index index.html index.htm index.php;
|
|
root /www/server/phpmyadmin;
|
|
#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
|
|
#error_page 404/404.html;
|
|
ssl_certificate /www/server/panel/ssl/certificate.pem;
|
|
ssl_certificate_key /www/server/panel/ssl/privateKey.pem;
|
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
|
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
|
|
ssl_prefer_server_ciphers on;
|
|
ssl_session_cache shared:SSL:10m;
|
|
ssl_session_timeout 10m;
|
|
error_page 497 https://$host$request_uri;
|
|
#SSL-END
|
|
%s
|
|
include enable-php.conf;
|
|
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
|
|
{
|
|
expires 30d;
|
|
}
|
|
location ~ .*\.(js|css)?$
|
|
{
|
|
expires 12h;
|
|
}
|
|
location ~ /\.
|
|
{
|
|
deny all;
|
|
}
|
|
access_log /www/wwwlogs/access.log;
|
|
}""" % auth
|
|
public.writeFile("/www/server/panel/vhost/nginx/phpmyadmin.conf",ssl_conf)
|
|
import panelPlugin
|
|
get.sName = "phpmyadmin"
|
|
v = panelPlugin.panelPlugin().get_soft_find(get)
|
|
if self._get_phpmyadmin_auth():
|
|
auth = """
|
|
#AUTH_START
|
|
AuthType basic
|
|
AuthName "Authorization "
|
|
AuthUserFile /www/server/pass/phpmyadmin.pass
|
|
Require user jose
|
|
#AUTH_END
|
|
"""
|
|
# apache配置
|
|
ssl_conf = '''Listen 887
|
|
<VirtualHost *:887>
|
|
ServerAdmin webmaster@example.com
|
|
DocumentRoot "/www/server/phpmyadmin"
|
|
ServerName 0b842aa5.phpmyadmin
|
|
ServerAlias phpmyadmin.com
|
|
#ErrorLog "/www/wwwlogs/BT_default_error.log"
|
|
#CustomLog "/www/wwwlogs/BT_default_access.log" combined
|
|
|
|
#SSL
|
|
SSLEngine On
|
|
SSLCertificateFile /www/server/panel/ssl/certificate.pem
|
|
SSLCertificateKeyFile /www/server/panel/ssl/privateKey.pem
|
|
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
|
|
SSLProtocol All -SSLv2 -SSLv3
|
|
SSLHonorCipherOrder On
|
|
|
|
#PHP
|
|
<FilesMatch \.php$>
|
|
SetHandler "proxy:{}"
|
|
</FilesMatch>
|
|
|
|
#DENY FILES
|
|
<Files ~ (\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)$>
|
|
Order allow,deny
|
|
Deny from all
|
|
</Files>
|
|
|
|
#PATH
|
|
<Directory "/www/wwwroot/bt.youbadbad.cn/">
|
|
{}
|
|
SetOutputFilter DEFLATE
|
|
Options FollowSymLinks
|
|
AllowOverride All
|
|
Require all granted
|
|
DirectoryIndex index.php index.html index.htm default.php default.html default.htm
|
|
</Directory>
|
|
</VirtualHost>'''.format(public.get_php_proxy(v["ext"]["phpversion"],'apache'),auth)
|
|
public.writeFile("/www/server/panel/vhost/apache/phpmyadmin.conf", ssl_conf)
|
|
else:
|
|
if os.path.exists("/www/server/panel/vhost/nginx/phpmyadmin.conf"):
|
|
os.remove("/www/server/panel/vhost/nginx/phpmyadmin.conf")
|
|
if os.path.exists("/www/server/panel/vhost/apache/phpmyadmin.conf"):
|
|
os.remove("/www/server/panel/vhost/apache/phpmyadmin.conf")
|
|
public.serviceReload()
|
|
return public.returnMsg(True, 'SET_SUCCESS')
|
|
public.serviceReload()
|
|
return public.returnMsg(True,'PHPMYADMIN_SSL_ERR5')
|
|
|
|
|
|
#设置PHPMyAdmin
|
|
def setPHPMyAdmin(self,get):
|
|
import re
|
|
#try:
|
|
filename = self.__get_webserver_conffile()
|
|
if public.get_webserver() == 'openlitespeed':
|
|
filename = "/www/server/panel/vhost/openlitespeed/detail/phpmyadmin.conf"
|
|
conf = public.readFile(filename)
|
|
if not conf: return public.returnMsg(False,'ERROR')
|
|
if hasattr(get,'port'):
|
|
mainPort = public.readFile('data/port.pl').strip()
|
|
rulePort = ['80','443','21','20','8080','8081','8089','11211','6379']
|
|
oldPort = "888"
|
|
if get.port in rulePort:
|
|
return public.returnMsg(False,'AJAX_PHPMYADMIN_PORT_ERR')
|
|
if public.get_webserver() == 'nginx':
|
|
rep = r"listen\s+([0-9]+)\s*;"
|
|
oldPort = re.search(rep,conf).groups()[0]
|
|
conf = re.sub(rep,'listen ' + get.port + ';\n',conf)
|
|
elif public.get_webserver() == 'apache':
|
|
rep = r"Listen\s+([0-9]+)\s*\n"
|
|
oldPort = re.search(rep,conf).groups()[0]
|
|
conf = re.sub(rep,"Listen " + get.port + "\n",conf,1)
|
|
rep = r"VirtualHost\s+\*:[0-9]+"
|
|
conf = re.sub(rep,"VirtualHost *:" + get.port,conf,1)
|
|
else:
|
|
filename = '/www/server/panel/vhost/openlitespeed/listen/888.conf'
|
|
conf = public.readFile(filename)
|
|
reg = r"address\s+\*:(\d+)"
|
|
tmp = re.search(reg,conf)
|
|
if tmp:
|
|
oldPort = tmp.groups(1)
|
|
conf = re.sub(reg,"address *:{}".format(get.port),conf)
|
|
if oldPort == get.port: return public.returnMsg(False,'SOFT_PHPVERSION_ERR_PORT')
|
|
|
|
public.writeFile(filename,conf)
|
|
import firewalls
|
|
get.ps = public.getMsg('SOFT_PHPVERSION_PS')
|
|
fw = firewalls.firewalls()
|
|
fw.AddAcceptPort(get)
|
|
public.serviceReload()
|
|
public.WriteLog('TYPE_SOFT','SOFT_PHPMYADMIN_PORT',(get.port,))
|
|
get.id = public.M('firewall').where('port=?',(oldPort,)).getField('id')
|
|
get.port = oldPort
|
|
fw.DelAcceptPort(get)
|
|
return public.returnMsg(True,'SET_PORT_SUCCESS')
|
|
|
|
if hasattr(get,'phpversion'):
|
|
if public.get_webserver() == 'nginx':
|
|
filename = public.GetConfigValue('setup_path') + '/nginx/conf/enable-php.conf'
|
|
conf = public.readFile(filename)
|
|
rep = r"(unix:/tmp/php-cgi.*\.sock|127.0.0.1:\d+)"
|
|
conf = re.sub(rep,public.get_php_proxy(get.phpversion,'nginx'),conf,1)
|
|
elif public.get_webserver() == 'apache':
|
|
rep = r"(unix:/tmp/php-cgi.*\.sock\|fcgi://localhost|fcgi://127.0.0.1:\d+)"
|
|
conf = re.sub(rep,public.get_php_proxy(get.phpversion,'apache'),conf,1)
|
|
else:
|
|
reg = r'/usr/local/lsws/lsphp\d+/bin/lsphp'
|
|
conf = re.sub(reg,'/usr/local/lsws/lsphp{}/bin/lsphp'.format(get.phpversion),conf)
|
|
public.writeFile(filename,conf)
|
|
public.serviceReload()
|
|
public.WriteLog('TYPE_SOFT','SOFT_PHPMYADMIN_PHP',(get.phpversion,))
|
|
return public.returnMsg(True,'SOFT_PHPVERSION_SET')
|
|
|
|
if hasattr(get,'password'):
|
|
import panelSite
|
|
if(get.password == 'close'):
|
|
return panelSite.panelSite().CloseHasPwd(get)
|
|
else:
|
|
return panelSite.panelSite().SetHasPwd(get)
|
|
|
|
if hasattr(get,'status'):
|
|
if conf.find(public.GetConfigValue('setup_path') + '/stop') != -1:
|
|
conf = conf.replace(public.GetConfigValue('setup_path') + '/stop',public.GetConfigValue('setup_path') + '/phpmyadmin')
|
|
msg = public.getMsg('START')
|
|
else:
|
|
conf = conf.replace(public.GetConfigValue('setup_path') + '/phpmyadmin',public.GetConfigValue('setup_path') + '/stop')
|
|
msg = public.getMsg('STOP')
|
|
|
|
public.writeFile(filename,conf)
|
|
public.serviceReload()
|
|
public.WriteLog('TYPE_SOFT','SOFT_PHPMYADMIN_STATUS',(msg,))
|
|
return public.returnMsg(True,'SOFT_PHPMYADMIN_STATUS',(msg,))
|
|
#except:
|
|
#return public.returnMsg(False,'ERROR');
|
|
|
|
def ToPunycode(self,get):
|
|
import re
|
|
get.domain = get.domain.encode('utf8')
|
|
tmp = get.domain.split('.')
|
|
newdomain = ''
|
|
for dkey in tmp:
|
|
#匹配非ascii字符
|
|
match = re.search(u"[\x80-\xff]+",dkey)
|
|
if not match:
|
|
newdomain += dkey + '.'
|
|
else:
|
|
newdomain += 'xn--' + dkey.decode('utf-8').encode('punycode') + '.'
|
|
|
|
return newdomain[0:-1]
|
|
|
|
#保存PHP排序
|
|
def phpSort(self,get):
|
|
if public.writeFile('/www/server/php/sort.pl',get.ssort): return public.returnMsg(True,'SUCCESS')
|
|
return public.returnMsg(False,'ERROR')
|
|
|
|
#获取广告代码
|
|
def GetAd(self,get):
|
|
try:
|
|
return public.HttpGet(public.GetConfigValue('home') + '/Api/GetAD?name='+get.name + '&soc=' + get.soc)
|
|
except:
|
|
return ''
|
|
|
|
#获取进度
|
|
def GetSpeed(self,get):
|
|
return public.getSpeed()
|
|
|
|
#检查登陆状态
|
|
def CheckLogin(self,get):
|
|
return True
|
|
|
|
#获取警告标识
|
|
def GetWarning(self,get):
|
|
warningFile = 'data/warning.json'
|
|
if not os.path.exists(warningFile): return public.returnMsg(False,'AJAX_WARNING_ERR')
|
|
import json,time;
|
|
wlist = json.loads(public.readFile(warningFile))
|
|
wlist['time'] = int(time.time())
|
|
return wlist
|
|
|
|
#设置警告标识
|
|
def SetWarning(self,get):
|
|
wlist = self.GetWarning(get)
|
|
id = int(get.id)
|
|
import time,json;
|
|
for i in xrange(len(wlist['data'])):
|
|
if wlist['data'][i]['id'] == id:
|
|
wlist['data'][i]['ignore_count'] += 1
|
|
wlist['data'][i]['ignore_time'] = int(time.time())
|
|
|
|
warningFile = 'data/warning.json'
|
|
public.writeFile(warningFile,json.dumps(wlist))
|
|
return public.returnMsg(True,'SET_SUCCESS')
|
|
|
|
#获取memcached状态
|
|
def GetMemcachedStatus(self,get):
|
|
import telnetlib,re;
|
|
conf = public.readFile('/etc/init.d/memcached')
|
|
result = {}
|
|
result['bind'] = re.search('IP=(.+)',conf).groups()[0]
|
|
result['port'] = int(re.search('PORT=(\d+)',conf).groups()[0])
|
|
result['maxconn'] = int(re.search('MAXCONN=(\d+)',conf).groups()[0])
|
|
result['cachesize'] = int(re.search('CACHESIZE=(\d+)',conf).groups()[0])
|
|
tn = telnetlib.Telnet(result['bind'],result['port'])
|
|
tn.write(b"stats\n")
|
|
tn.write(b"quit\n")
|
|
data = tn.read_all()
|
|
if type(data) == bytes: data = data.decode('utf-8')
|
|
data = data.replace('STAT','').replace('END','').split("\n")
|
|
res = ['cmd_get','get_hits','get_misses','limit_maxbytes','curr_items','bytes','evictions','limit_maxbytes','bytes_written','bytes_read','curr_connections'];
|
|
for d in data:
|
|
if len(d)<3: continue
|
|
t = d.split()
|
|
if not t[0] in res: continue
|
|
result[t[0]] = int(t[1])
|
|
result['hit'] = 1
|
|
if result['get_hits'] > 0 and result['cmd_get'] > 0:
|
|
result['hit'] = float(result['get_hits']) / float(result['cmd_get']) * 100
|
|
|
|
return result
|
|
|
|
#设置memcached缓存大小
|
|
def SetMemcachedCache(self,get):
|
|
import re
|
|
confFile = '/etc/init.d/memcached'
|
|
conf = public.readFile(confFile)
|
|
conf = re.sub('IP=.+','IP='+get.ip,conf)
|
|
conf = re.sub('PORT=\d+','PORT='+get.port,conf)
|
|
conf = re.sub('MAXCONN=\d+','MAXCONN='+get.maxconn,conf)
|
|
conf = re.sub('CACHESIZE=\d+','CACHESIZE='+get.cachesize,conf)
|
|
public.writeFile(confFile,conf)
|
|
public.ExecShell(confFile + ' reload')
|
|
return public.returnMsg(True,'SET_SUCCESS')
|
|
|
|
#取redis状态
|
|
def GetRedisStatus(self,get):
|
|
import re
|
|
c = public.readFile('/www/server/redis/redis.conf')
|
|
port = re.findall('\n\s*port\s+(\d+)',c)[0]
|
|
password = re.findall('\n\s*requirepass\s+(.+)',c)
|
|
if password:
|
|
password = ' -a ' + password[0]
|
|
else:
|
|
password = ''
|
|
data = public.ExecShell('/www/server/redis/src/redis-cli -p ' + port + password + ' info')[0];
|
|
res = [
|
|
'tcp_port',
|
|
'uptime_in_days', #已运行天数
|
|
'connected_clients', #连接的客户端数量
|
|
'used_memory', #Redis已分配的内存总量
|
|
'used_memory_rss', #Redis占用的系统内存总量
|
|
'used_memory_peak', #Redis所用内存的高峰值
|
|
'mem_fragmentation_ratio', #内存碎片比率
|
|
'total_connections_received',#运行以来连接过的客户端的总数量
|
|
'total_commands_processed', #运行以来执行过的命令的总数量
|
|
'instantaneous_ops_per_sec', #服务器每秒钟执行的命令数量
|
|
'keyspace_hits', #查找数据库键成功的次数
|
|
'keyspace_misses', #查找数据库键失败的次数
|
|
'latest_fork_usec' #最近一次 fork() 操作耗费的毫秒数
|
|
]
|
|
data = data.split("\n")
|
|
result = {}
|
|
for d in data:
|
|
if len(d)<3: continue
|
|
t = d.strip().split(':')
|
|
if not t[0] in res: continue
|
|
result[t[0]] = t[1]
|
|
return result
|
|
|
|
#取PHP-FPM日志
|
|
def GetFpmLogs(self,get):
|
|
import re
|
|
fpm_path = '/www/server/php/' + get.version + '/etc/php-fpm.conf'
|
|
if not os.path.exists(fpm_path): return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
|
|
fpm_conf = public.readFile(fpm_path)
|
|
log_tmp = re.findall(r"error_log\s*=\s*(.+)",fpm_conf)
|
|
if not log_tmp: return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
|
|
log_file = log_tmp[0].strip()
|
|
if log_file.find('var/log') == 0:
|
|
log_file = '/www/server/php/' +get.version + '/'+ log_file
|
|
return public.returnMsg(True,public.GetNumLines(log_file,1000))
|
|
|
|
#取PHP慢日志
|
|
def GetFpmSlowLogs(self,get):
|
|
import re
|
|
fpm_path = '/www/server/php/' + get.version + '/etc/php-fpm.conf'
|
|
if not os.path.exists(fpm_path): return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
|
|
fpm_conf = public.readFile(fpm_path)
|
|
log_tmp = re.findall(r"slowlog\s*=\s*(.+)",fpm_conf)
|
|
if not log_tmp: return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
|
|
log_file = log_tmp[0].strip()
|
|
if log_file.find('var/log') == 0:
|
|
log_file = '/www/server/php/' +get.version + '/'+ log_file
|
|
return public.returnMsg(True,public.GetNumLines(log_file,1000))
|
|
|
|
#取指定日志
|
|
def GetOpeLogs(self,get):
|
|
if not os.path.exists(get.path): return public.returnMsg(False,'AJAX_LOG_FILR_NOT_EXISTS')
|
|
return public.returnMsg(True,public.GetNumLines(get.path,1000))
|
|
|
|
#检查用户绑定是否正确
|
|
def check_user_auth(self,get):
|
|
import requests
|
|
m_key = 'check_user_auth'
|
|
if m_key in session: return session[m_key]
|
|
u_path = 'data/userInfo.json'
|
|
try:
|
|
userInfo = json.loads(public.ReadFile(u_path))
|
|
except:
|
|
if os.path.exists(u_path): os.remove(u_path)
|
|
return public.returnMsg(False,'AJAX_USER_BE_OVERDUE')
|
|
url_headers = {"authorization":"bt {}".format(userInfo['token'])}
|
|
resp = requests.post('{}/api/user/verifyToken'.format(self.__official_url),headers=url_headers)
|
|
resp = resp.json()
|
|
if not resp['success']:
|
|
if os.path.exists(u_path): os.remove(u_path)
|
|
return public.returnMsg(False,'AJAX_USER_BE_OVERDUE')
|
|
else:
|
|
session[m_key] = public.returnMsg(True,'AJAX_USER_IS_VALID')
|
|
return session[m_key]
|
|
|
|
#PHP探针
|
|
def php_info(self,args):
|
|
php_version = args.php_version.replace('.','')
|
|
php_path = '/www/server/php/'
|
|
if public.get_webserver() == 'openlitespeed':
|
|
php_path = '/usr/local/lsws/lsphp'
|
|
php_bin = php_path + php_version + '/bin/php'
|
|
php_ini = php_path + php_version + '/etc/php.ini'
|
|
if not os.path.exists('/etc/redhat-release') and public.get_webserver() == 'openlitespeed':
|
|
php_ini = php_path + php_version + '/etc/php/'+args.php_version+'/litespeed/php.ini'
|
|
tmp = public.ExecShell(php_bin + ' /www/server/panel/class/php_info.php')[0]
|
|
if tmp.find('Warning: JIT is incompatible') != -1:
|
|
tmp = tmp.strip().split('\n')[-1]
|
|
result = json.loads(tmp)
|
|
result['phpinfo'] = {}
|
|
result['phpinfo']['php_version'] = result['php_version']
|
|
result['phpinfo']['php_path'] = php_path
|
|
result['phpinfo']['php_bin'] = php_bin
|
|
result['phpinfo']['php_ini'] = php_ini
|
|
result['phpinfo']['modules'] = ' '.join(result['modules'])
|
|
result['phpinfo']['ini'] = result['ini']
|
|
result['phpinfo']['keys'] = { "1cache": "Buffer", "2crypt": "Encryption and decryption library", "0db": "Database-driven", "4network": "Network Communication Library", "5io_string": "File and string processing libraries", "3photo":"Image processing library","6other":"Other third-party libraries"}
|
|
del(result['php_version'])
|
|
del(result['modules'])
|
|
del(result['ini'])
|
|
return result
|
|
|
|
#取指定行
|
|
def get_lines(self,args):
|
|
if not os.path.exists(args.filename): return public.returnMsg(False,'LOG_EMPTY')
|
|
s_body = public.ExecShell("tail -n {} {}".format(args.num,args.filename))[0]
|
|
return public.returnMsg(True,s_body)
|
|
|
|
|