mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
Submit aaPanel version 6.0.5
This commit is contained in:
@@ -0,0 +1,454 @@
|
||||
#coding: utf-8
|
||||
#-------------------------------------------------------------------
|
||||
# 宝塔Linux面板
|
||||
#-------------------------------------------------------------------
|
||||
# Copyright (c) 2019-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
#-------------------------------------------------------------------
|
||||
# Author: 黄文良 <287962566@qq.com>
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#------------------------------
|
||||
# 消息队列
|
||||
#------------------------------
|
||||
import sys,os
|
||||
sys.path.insert(0,'/www/server/panel/class')
|
||||
os.chdir('/www/server/panel')
|
||||
import public,time,downloadFile,json
|
||||
|
||||
|
||||
class bt_task:
|
||||
__table = 'task_list'
|
||||
__task_tips = '/dev/shm/bt_task_now.pl'
|
||||
__task_path = '/www/server/panel/tmp/'
|
||||
def __init__(self):
|
||||
|
||||
#创建数据表
|
||||
sql = '''CREATE TABLE IF NOT EXISTS `task_list` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`name` TEXT,
|
||||
`type` TEXT,
|
||||
`status` INTEGER,
|
||||
`shell` TEXT,
|
||||
`other` TEXT,
|
||||
`exectime` INTEGER,
|
||||
`endtime` INTEGER,
|
||||
`addtime` INTEGER
|
||||
);'''
|
||||
public.M(None).execute(sql,())
|
||||
|
||||
#创建临时目录
|
||||
if not os.path.exists(self.__task_path): os.makedirs(self.__task_path,384)
|
||||
|
||||
#取任务列表
|
||||
def get_task_list(self,status=-3):
|
||||
sql = public.M(self.__table)
|
||||
if status != -3:
|
||||
sql = sql.where('status=?',(status,))
|
||||
data = sql.field('id,name,type,shell,other,status,exectime,endtime,addtime').select();
|
||||
return data
|
||||
|
||||
#取任务列表前端
|
||||
def get_task_lists(self,get):
|
||||
sql = public.M(self.__table)
|
||||
if 'status' in get:
|
||||
if get.status == '-3':
|
||||
sql = sql.where('status=? OR status=?',(-1,0))
|
||||
else:
|
||||
sql = sql.where('status=?',(get.status,))
|
||||
data = sql.field('id,name,type,shell,other,status,exectime,endtime,addtime').order('id asc').limit('10').select();
|
||||
if not 'num' in get: get.num = 15
|
||||
num = int(get.num)
|
||||
for i in range(len(data)):
|
||||
data[i]['log'] = ''
|
||||
if data[i]['status'] == -1:
|
||||
data[i]['log'] = self.get_task_log(data[i]['id'],data[i]['type'],num)
|
||||
elif data[i]['status'] == 1:
|
||||
data[i]['log'] = self.get_task_log(data[i]['id'],data[i]['type'],10)
|
||||
if data[i]['type'] == '3':
|
||||
data[i]['other'] = json.loads(data[i]['other'])
|
||||
return data
|
||||
|
||||
#创建任务
|
||||
def create_task(self,task_name,task_type,task_shell,other=''):
|
||||
self.clean_log()
|
||||
public.M(self.__table).add('name,type,shell,other,addtime,status',(task_name,task_type,task_shell,other,int(time.time()),0))
|
||||
public.WriteFile(self.__task_tips,'True')
|
||||
os.system("/etc/init.d/bt start")
|
||||
return True
|
||||
|
||||
|
||||
#修改任务
|
||||
def modify_task(self,id,key,value):
|
||||
public.M(self.__table).where('id=?',(id,)).setField(key,value)
|
||||
return True
|
||||
|
||||
#删除任务
|
||||
def remove_task(self,get):
|
||||
task_info = self.get_task_find(get.id)
|
||||
public.M(self.__table).where('id=?',(get.id,)).delete();
|
||||
if str(task_info['status']) == '-1':
|
||||
os.system("kill -9 $(ps aux|grep 'task.py'|grep -v grep|awk '{print $2}')")
|
||||
if task_info['type'] == '1':
|
||||
if os.path.exists(task_info['other']): os.remove(task_info['other'])
|
||||
elif task_info['type'] == '3':
|
||||
z_info = json.loads(task_info['other'])
|
||||
if z_info['z_type'] == 'tar.gz':
|
||||
os.system("kill -9 $(ps aux|grep 'tar -zcvf'|grep -v grep|awk '{print $2}')")
|
||||
elif z_info['z_type'] == 'rar':
|
||||
os.system("kill -9 $(ps aux|grep /www/server/rar/rar|grep -v grep|awk '{print $2}')")
|
||||
elif z_info['z_type'] == 'zip':
|
||||
os.system("kill -9 $(ps aux|grep '.zip -r'|grep -v grep|awk '{print $2}')")
|
||||
os.system("kill -9 $(ps aux|grep '.zip\' -r'|grep -v grep|awk '{print $2}')")
|
||||
if os.path.exists(z_info['dfile']): os.remove(z_info['dfile'])
|
||||
elif task_info['type'] == '2':
|
||||
os.system("kill -9 $(ps aux|grep 'tar -zxvf'|grep -v grep|awk '{print $2}')")
|
||||
os.system("kill -9 $(ps aux|grep '/www/server/rar/unrar'|grep -v grep|awk '{print $2}')")
|
||||
os.system("kill -9 $(ps aux|grep 'unzip -P'|grep -v grep|awk '{print $2}')")
|
||||
os.system("kill -9 $(ps aux|grep 'gunzip -c'|grep -v grep|awk '{print $2}')")
|
||||
elif task_info['type'] == '0':
|
||||
os.system("kill -9 $(ps aux|grep '"+task_info['shell']+"'|grep -v grep|awk '{print $2}')")
|
||||
|
||||
os.system("/etc/init.d/bt start")
|
||||
return public.returnMsg(True,'TASK_CANCEL')
|
||||
|
||||
#取一条任务
|
||||
def get_task_find(self,id):
|
||||
data = public.M(self.__table).where('id=?',(id,)).field('id,name,type,shell,other,status,exectime,endtime,addtime').find()
|
||||
return data
|
||||
|
||||
#执行任务
|
||||
#task_type 0.执行shell 1.下载文件 2.解压文件 3.压缩文件
|
||||
def execute_task(self,id,task_type,task_shell,other=''):
|
||||
if not os.path.exists(self.__task_path): os.makedirs(self.__task_path,384)
|
||||
log_file = self.__task_path + str(id) + '.log'
|
||||
|
||||
#标记状态执行时间
|
||||
self.modify_task(id,'status',-1)
|
||||
self.modify_task(id,'exectime',int(time.time()))
|
||||
task_type = int(task_type)
|
||||
#开始执行
|
||||
if task_type == 0: #执行命令
|
||||
os.system(task_shell + ' &> ' + log_file)
|
||||
elif task_type == 1: #下载文件
|
||||
down_file = downloadFile.downloadFile()
|
||||
down_file.logPath = log_file
|
||||
print(down_file.DownloadFile(task_shell,other))
|
||||
elif task_type == 2: #解压文件
|
||||
zip_info = json.loads(other)
|
||||
self._unzip(task_shell,zip_info['dfile'],zip_info['password'],log_file)
|
||||
elif task_type == 3: #压缩文件
|
||||
zip_info = json.loads(other)
|
||||
if not 'z_type' in zip_info: zip_info['z_type'] = 'tar.gz'
|
||||
print(self._zip(task_shell,zip_info['sfile'],zip_info['dfile'],log_file,zip_info['z_type']))
|
||||
elif task_type == 4: #备份数据库
|
||||
self.backup_database(task_shell,log_file)
|
||||
elif task_type == 5: #导入数据库
|
||||
self.input_database(task_shell,other,log_file)
|
||||
elif task_type == 6: #备份网站
|
||||
self.backup_site(task_shell,log_file)
|
||||
elif task_type == 7: #恢复网站
|
||||
pass
|
||||
|
||||
#标记状态与结束时间
|
||||
self.modify_task(id,'status',1)
|
||||
self.modify_task(id,'endtime',int(time.time()))
|
||||
|
||||
#开始检测任务
|
||||
def start_task(self):
|
||||
noe = False
|
||||
while True:
|
||||
try:
|
||||
time.sleep(1);
|
||||
if not os.path.exists(self.__task_tips) and noe: continue;
|
||||
if os.path.exists(self.__task_tips): os.remove(self.__task_tips)
|
||||
public.M(self.__table).where('status=?',('-1',)).setField('status',0)
|
||||
task_list = self.get_task_list(0)
|
||||
for task_info in task_list:
|
||||
self.execute_task(task_info['id'],task_info['type'],task_info['shell'],task_info['other'])
|
||||
noe = True
|
||||
except: print(public.get_error_info())
|
||||
|
||||
#取任务执行日志
|
||||
def get_task_log(self,id,task_type,num=5):
|
||||
log_file = self.__task_path + str(id) + '.log'
|
||||
if not os.path.exists(log_file):
|
||||
data = ''
|
||||
if(task_type == '1'): data = {'name':public.GetMsg("DOWNLOAD_FILE"),'total':0,'used':0,'pre':0,'speed':0}
|
||||
return data
|
||||
data = public.GetNumLines(log_file,num)
|
||||
n = 0
|
||||
if(task_type == '1'):
|
||||
try:
|
||||
data = json.loads(data)
|
||||
except:
|
||||
if n < 3:
|
||||
time.sleep(2);
|
||||
n+=1
|
||||
self.get_task_log(id,task_type,num)
|
||||
else:
|
||||
data = {'name':public.GetMsg("DOWNLOAD_FILE"),'total':0,'used':0,'pre':0,'speed':0}
|
||||
if data == [] and n < 3:
|
||||
time.sleep(1);
|
||||
n+=1
|
||||
self.get_task_log(id,task_type,num)
|
||||
else:
|
||||
if type(data) == list: return ''
|
||||
data = data.replace('\x08','').replace('\n','<br>')
|
||||
|
||||
return data
|
||||
|
||||
#清理任务日志
|
||||
def clean_log(self):
|
||||
s_time = int(time.time())
|
||||
timeout = 86400
|
||||
for f in os.listdir(self.__task_path):
|
||||
filename = self.__task_path + f
|
||||
c_time = os.stat(filename).st_ctime
|
||||
if s_time - c_time > timeout: os.remove(filename)
|
||||
return True
|
||||
|
||||
#文件压缩
|
||||
def _zip(self,path,sfile,dfile,log_file,z_type='tar.gz'):
|
||||
if sys.version_info[0] == 2:
|
||||
sfile = sfile.encode('utf-8')
|
||||
dfile = dfile.encode('utf-8')
|
||||
if sys.version_info[0] == 2: path = path.encode('utf-8');
|
||||
if sfile.find(',') == -1:
|
||||
if not os.path.exists(path+'/'+sfile): return public.returnMsg(False,'FILE_NOT_EXISTS');
|
||||
#处理多文件压缩
|
||||
sfiles = ''
|
||||
for sfile in sfile.split(','):
|
||||
if not sfile: continue;
|
||||
sfiles += " '" + sfile + "'";
|
||||
|
||||
#判断压缩格式
|
||||
if z_type == 'zip':
|
||||
os.system("cd '"+path+"' && zip '"+dfile+"' -r "+sfiles+" &> "+log_file)
|
||||
elif z_type == 'tar.gz':
|
||||
os.system("cd '" + path + "' && tar -zcvf '" + dfile + "' " + sfiles + " &> " + log_file);
|
||||
elif z_type == 'rar':
|
||||
rar_file = '/www/server/rar/rar'
|
||||
if not os.path.exists(rar_file): self.install_rar()
|
||||
os.system("cd '" + path + "' && "+rar_file+" a -r '" + dfile + "' " + sfiles + " &> " + log_file)
|
||||
else:
|
||||
return public.returnMsg(False,'NOT_SUP_COMP_FORMAT')
|
||||
|
||||
self.set_file_accept(dfile);
|
||||
public.WriteLog("TYPE_FILE", 'ZIP_SUCCESS',(sfiles,dfile));
|
||||
return public.returnMsg(True,'ZIP_SUCCESS')
|
||||
|
||||
|
||||
#文件解压
|
||||
def _unzip(self,sfile,dfile,password,log_file):
|
||||
if sys.version_info[0] == 2:
|
||||
sfile = sfile.encode('utf-8');
|
||||
dfile = dfile.encode('utf-8');
|
||||
if not os.path.exists(sfile):
|
||||
return public.returnMsg(False,'FILE_NOT_EXISTS');
|
||||
|
||||
#判断压缩包格式
|
||||
if sfile[-4:] == '.zip':
|
||||
os.system("unzip -P '"+password+"' -o '" + sfile + "' -d '" + dfile + "' &> " + log_file)
|
||||
elif sfile[-7:] == '.tar.gz' or sfile[-4:] == '.tgz':
|
||||
os.system("tar zxvf '" + sfile + "' -C '" + dfile + "' &> " + log_file)
|
||||
elif sfile[-4:] == '.rar':
|
||||
rar_file = '/www/server/rar/unrar'
|
||||
if not os.path.exists(rar_file): self.install_rar()
|
||||
os.system('echo "'+password+'"|' + rar_file + ' x -u -y "' + sfile + '" "' + dfile + '" &> ' + log_file)
|
||||
elif sfile[-4:] == '.war':
|
||||
os.system("unzip -P '"+password+"' -o '" + sfile + "' -d '" + dfile + "' &> " + log_file)
|
||||
else:
|
||||
os.system("gunzip -c " + sfile + " > " + sfile[:-3])
|
||||
|
||||
#检查是否设置权限
|
||||
if self.check_dir(dfile):
|
||||
sites_path = public.M('config').where('id=?',(1,)).getField('sites_path');
|
||||
if dfile.find('/www/wwwroot') != -1 or dfile.find(sites_path) != -1:
|
||||
self.set_file_accept(dfile);
|
||||
else:
|
||||
import pwd
|
||||
user = pwd.getpwuid(os.stat(dfile).st_uid).pw_name
|
||||
os.system("chown %s:%s %s" % (user,user,dfile))
|
||||
|
||||
public.WriteLog("TYPE_FILE", 'UNZIP_SUCCESS',(sfile,dfile));
|
||||
return public.returnMsg(True,'UNZIP_SUCCESS');
|
||||
|
||||
#备份网站
|
||||
def backup_site(self,id,log_file):
|
||||
find = public.M('sites').where("id=?",(id,)).field('name,path,id').find();
|
||||
fileName = find['name']+'_'+time.strftime('%Y%m%d_%H%M%S',time.localtime())+'.zip';
|
||||
backupPath = public.M('config').where('id=?',(1,)).getField('backup_path') + '/site'
|
||||
|
||||
zipName = backupPath + '/'+fileName;
|
||||
if not (os.path.exists(backupPath)): os.makedirs(backupPath)
|
||||
|
||||
execStr = "cd '" + find['path'] + "' && zip '" + zipName + "' -x .user.ini -r ./ &> " + log_file
|
||||
os.system(execStr)
|
||||
|
||||
sql = public.M('backup').add('type,name,pid,filename,size,addtime',(0,fileName,find['id'],zipName,0,public.getDate()));
|
||||
public.WriteLog('TYPE_SITE', 'SITE_BACKUP_SUCCESS',(find['name'],));
|
||||
return public.returnMsg(True, 'BACKUP_SUCCESS');
|
||||
|
||||
#备份数据库
|
||||
def backup_database(self,id,log_file):
|
||||
name = public.M('databases').where("id=?",(id,)).getField('name')
|
||||
find = public.M('config').where('id=?',(1,)).field('mysql_root,backup_path').find()
|
||||
|
||||
if not os.path.exists(find['backup_path'] + '/database'): os.system('mkdir -p ' + find['backup_path'] + '/database')
|
||||
self.mypass(True, find['mysql_root'])
|
||||
|
||||
fileName = name + '_' + time.strftime('%Y%m%d_%H%M%S',time.localtime()) + '.sql.gz'
|
||||
backupName = find['backup_path'] + '/database/' + fileName
|
||||
os.system("/www/server/mysql/bin/mysqldump --force --opt \"" + name + "\" | gzip > " + backupName)
|
||||
if not os.path.exists(backupName): return public.returnMsg(False,'BACKUP_ERROR')
|
||||
|
||||
self.mypass(False, find['mysql_root'])
|
||||
|
||||
sql = public.M('backup')
|
||||
addTime = time.strftime('%Y-%m-%d %X',time.localtime())
|
||||
sql.add('type,name,pid,filename,size,addtime',(1,fileName,id,backupName,0,addTime))
|
||||
public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS",(name,))
|
||||
return public.returnMsg(True, 'BACKUP_SUCCESS')
|
||||
|
||||
#导入数据库
|
||||
def input_database(self,id,file,log_file):
|
||||
name = public.M('databases').where("id=?",(id,)).getField('name')
|
||||
root = public.M('config').where('id=?',(1,)).getField('mysql_root');
|
||||
tmp = file.split('.')
|
||||
exts = ['sql','gz','zip']
|
||||
ext = tmp[len(tmp) -1]
|
||||
if ext not in exts:
|
||||
return public.returnMsg(False, 'DATABASE_INPUT_ERR_FORMAT')
|
||||
|
||||
isgzip = False
|
||||
if ext != 'sql':
|
||||
tmp = file.split('/')
|
||||
tmpFile = tmp[len(tmp)-1]
|
||||
tmpFile = tmpFile.replace('.sql.' + ext, '.sql')
|
||||
tmpFile = tmpFile.replace('.' + ext, '.sql')
|
||||
tmpFile = tmpFile.replace('tar.', '')
|
||||
backupPath = public.M('config').where('id=?',(1,)).getField('backup_path') + '/database'
|
||||
|
||||
if ext == 'zip':
|
||||
public.ExecShell("cd " + backupPath + " && unzip " + file)
|
||||
else:
|
||||
public.ExecShell("cd " + backupPath + " && tar zxf " + file)
|
||||
if not os.path.exists(backupPath + "/" + tmpFile):
|
||||
public.ExecShell("cd " + backupPath + " && gunzip -q " + file)
|
||||
isgizp = True
|
||||
|
||||
if not os.path.exists(backupPath + '/' + tmpFile) or tmpFile == '': return public.returnMsg(False, 'FILE_NOT_EXISTS',(tmpFile,))
|
||||
self.mypass(True, root);
|
||||
os.system(public.GetConfigValue('setup_path') + "/mysql/bin/mysql -uroot -p" + root + " --force \"" + name + "\" < " + backupPath + '/' +tmpFile)
|
||||
self.mypass(False, root);
|
||||
if isgizp:
|
||||
os.system('cd ' +backupPath+ ' && gzip ' + file.split('/')[-1][:-3]);
|
||||
else:
|
||||
os.system("rm -f " + backupPath + '/' +tmpFile)
|
||||
else:
|
||||
self.mypass(True, root);
|
||||
os.system(public.GetConfigValue('setup_path') + "/mysql/bin/mysql -uroot -p" + root + " --force \"" + name + "\" < " + file)
|
||||
self.mypass(False, root);
|
||||
|
||||
|
||||
public.WriteLog("TYPE_DATABASE", 'DATABASE_INPUT_SUCCESS',(name,))
|
||||
return public.returnMsg(True, 'DATABASE_INPUT_SUCCESS');
|
||||
|
||||
|
||||
|
||||
#配置
|
||||
def mypass(self,act,root):
|
||||
my_cnf = '/etc/my.cnf'
|
||||
os.system("sed -i '/user=root/d' " + my_cnf)
|
||||
os.system("sed -i '/password=/d' " + my_cnf)
|
||||
if act:
|
||||
mycnf = public.readFile(my_cnf);
|
||||
rep = "\[mysqldump\]\nuser=root"
|
||||
sea = "[mysqldump]\n"
|
||||
subStr = sea + "user=root\npassword=\"" + root + "\"\n";
|
||||
mycnf = mycnf.replace(sea,subStr)
|
||||
if len(mycnf) > 100: public.writeFile(my_cnf,mycnf);
|
||||
|
||||
#设置权限
|
||||
def set_file_accept(self,filename):
|
||||
os.system('chown -R www:www ' + filename)
|
||||
os.system('chmod -R 755 ' + filename)
|
||||
|
||||
#检查敏感目录
|
||||
def check_dir(self,path):
|
||||
path = path.replace('//','/');
|
||||
if path[-1:] == '/':
|
||||
path = path[:-1]
|
||||
|
||||
nDirs = ('',
|
||||
'/',
|
||||
'/*',
|
||||
'/www',
|
||||
'/root',
|
||||
'/boot',
|
||||
'/bin',
|
||||
'/etc',
|
||||
'/home',
|
||||
'/dev',
|
||||
'/sbin',
|
||||
'/var',
|
||||
'/usr',
|
||||
'/tmp',
|
||||
'/sys',
|
||||
'/proc',
|
||||
'/media',
|
||||
'/mnt',
|
||||
'/opt',
|
||||
'/lib',
|
||||
'/srv',
|
||||
'/selinux',
|
||||
'/www/server',
|
||||
'/www/server/data',
|
||||
public.GetConfigValue('logs_path'),
|
||||
public.GetConfigValue('setup_path'))
|
||||
|
||||
return not path in nDirs
|
||||
|
||||
#安装rar组件
|
||||
def install_rar(self):
|
||||
unrar_file = '/www/server/rar/unrar'
|
||||
rar_file = '/www/server/rar/rar'
|
||||
bin_unrar = '/usr/local/bin/unrar'
|
||||
bin_rar = '/usr/local/bin/rar'
|
||||
if os.path.exists(unrar_file) and os.path.exists(bin_unrar):
|
||||
try:
|
||||
import rarfile
|
||||
except:
|
||||
os.system("pip install rarfile")
|
||||
return True
|
||||
|
||||
import platform
|
||||
os_bit = ''
|
||||
if platform.machine() == 'x86_64': os_bit = '-x64';
|
||||
download_url = public.get_url() + '/src/rarlinux'+os_bit+'-5.6.1.tar.gz';
|
||||
|
||||
tmp_file = '/tmp/bt_rar.tar.gz'
|
||||
os.system('wget -O ' + tmp_file + ' ' + download_url)
|
||||
if os.path.exists(unrar_file): os.system("rm -rf /www/server/rar")
|
||||
os.system("tar xvf " + tmp_file + ' -C /www/server/')
|
||||
if os.path.exists(tmp_file): os.remove(tmp_file)
|
||||
if not os.path.exists(unrar_file): return False
|
||||
|
||||
if os.path.exists(bin_unrar): os.remove(bin_unrar)
|
||||
if os.path.exists(bin_rar): os.remove(bin_rar)
|
||||
|
||||
os.system('ln -sf ' + unrar_file + ' ' + bin_unrar)
|
||||
os.system('ln -sf ' + rar_file + ' ' + bin_rar)
|
||||
#os.system("pip install rarfile")
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
p = bt_task()
|
||||
#p.create_task('测试执行SHELL',0,'yum install wget -y','')
|
||||
#print(p.get_task_list())
|
||||
#p.modify_task(3,'status',0)
|
||||
#p.modify_task(3,'shell','bash /www/server/panel/install/install_soft.sh 0 update php 5.6')
|
||||
#p.modify_task(1,'other','{"sfile":"BTPanel","dfile":"/www/test.rar","z_type":"rar"}')
|
||||
p.start_task()
|
||||
#p._zip(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5])
|
||||
Reference in New Issue
Block a user