mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
1. Added Mail Marketing Automation trigger tasks 2. Added Mail Marketing Groups Import, Export, Merge 3. Added Mail Marketing Subscribers to support paste import 4. Added Mail Marketing Template Import Export Duplicate 5. Added Mail server add timed automatic reply 6. Added HTTPS Protection function for Website (disables automatic HTTP to HTTPS redirection when enabled) 7. Optimize Website Interface Button Integration 8. Optimize the response speed of WP Toolkit interface
323 lines
10 KiB
Python
323 lines
10 KiB
Python
#coding: utf-8
|
|
#-------------------------------------------------------------------
|
|
# aaPanel
|
|
#-------------------------------------------------------------------
|
|
# Copyright (c) 2015-2099 aaPanel(www.aapanel.com) All rights reserved.
|
|
#-------------------------------------------------------------------
|
|
# Author: cjxin <bt_ahong@aapanel.com>
|
|
#-------------------------------------------------------------------
|
|
|
|
#------------------------------
|
|
# 面板日志类
|
|
#------------------------------
|
|
|
|
import os,re,json,time
|
|
from logsModel.base import logsBase
|
|
import public,db
|
|
from html import unescape,escape
|
|
|
|
class main(logsBase):
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
|
|
def get_logs_info(self,args):
|
|
'''
|
|
@name 获取分类日志信息
|
|
'''
|
|
data = public.M('logs').query('''
|
|
select type,count(id) as 'count' from logs
|
|
group by type
|
|
order by count(id) desc
|
|
''')
|
|
result = []
|
|
for arrs in data:
|
|
item = {}
|
|
if not arrs: continue
|
|
|
|
item['count'] = arrs[1]
|
|
item['type'] = arrs[0]
|
|
result.append(item)
|
|
public.set_module_logs('get_logs_info','get_logs_info')
|
|
return public.return_message(0, 0, result)
|
|
|
|
def get_logs_bytype(self,args):
|
|
"""
|
|
@name 根据类型获取日志
|
|
@param args.type 日志类型
|
|
"""
|
|
p,limit = 1,20
|
|
if 'p' in args: p = int(args.p)
|
|
if 'limit' in args: limit = int(args.limit)
|
|
|
|
stype = args.stype
|
|
search = '[' + str(args.search) + ']'
|
|
|
|
where = "type=? and log like ? "
|
|
|
|
count = public.M('logs').where(where,(stype,'%'+search+'%')).count()
|
|
data = public.get_page(count,p,limit)
|
|
data['data'] = public.M('logs').where(where,(stype,'%'+search+'%')).limit('{},{}'.format(data['shift'], data['row'])).order('id desc').select()
|
|
|
|
return public.return_message(0, 0, data)
|
|
|
|
|
|
def __get_panel_dirs(self):
|
|
'''
|
|
@name 获取面板日志目录
|
|
'''
|
|
dirs = []
|
|
for filename in os.listdir('{}/logs/request'.format(public.get_panel_path())):
|
|
if filename.find('.json') != -1:
|
|
dirs.append(filename)
|
|
|
|
dirs = sorted(dirs,reverse=True)
|
|
return dirs
|
|
|
|
|
|
|
|
def get_panel_log(self,get):
|
|
"""
|
|
@name 获取面板日志
|
|
"""
|
|
p,limit,search = 1,20,''
|
|
if 'p' in get: p = int(get.p)
|
|
if 'limit' in get: limit = int(get.limit)
|
|
if 'search' in get: search = get.search
|
|
|
|
find_idx = 0
|
|
log_list = []
|
|
dirs = self.__get_panel_dirs()
|
|
for filename in dirs:
|
|
log_path = '{}/logs/request/{}'.format(public.get_panel_path(),filename)
|
|
if not os.path.exists(log_path): #文件不存在
|
|
continue
|
|
|
|
if len(log_list) >= limit:
|
|
break
|
|
|
|
p_num = 0 #分页计数器
|
|
next_file = False
|
|
while not next_file:
|
|
if len(log_list) >= limit:
|
|
break
|
|
p_num += 1
|
|
result = self.GetNumLines(log_path,10001,p_num).split('\r\n')
|
|
if len(result) < 10000:
|
|
next_file = True
|
|
result.reverse()
|
|
for _line in result:
|
|
if not _line: continue
|
|
if len(log_list) >= limit:
|
|
break
|
|
|
|
try:
|
|
if self.find_line_str(_line,search):
|
|
find_idx += 1
|
|
|
|
if find_idx > (p-1) * limit:
|
|
|
|
info = json.loads(unescape(_line))
|
|
for key in info:
|
|
if isinstance(info[key],str):
|
|
info[key] = escape(info[key])
|
|
|
|
info['address'] = info['ip'].split(':')[0]
|
|
log_list.append(info)
|
|
except:pass
|
|
|
|
# return public.return_area(log_list,'address')
|
|
return public.return_message(0, 0, log_list)
|
|
|
|
def get_panel_error_logs(self,get):
|
|
'''
|
|
@name 获取面板错误日志
|
|
'''
|
|
search = ''
|
|
if 'search' in get:
|
|
search = get.search
|
|
filename = '{}/logs/error.log'.format(public.get_panel_path())
|
|
if not os.path.exists(filename):
|
|
return public.return_message(-1, 0, public.lang("No error log"))
|
|
|
|
res = {}
|
|
res['data'] = public.xssdecode(self.GetNumLines(filename,2000,1,search))
|
|
res['data'].reverse()
|
|
return public.return_message(0, 0, res)
|
|
|
|
|
|
def __get_ftp_log_files(self,path):
|
|
"""
|
|
@name 获取FTP日志文件列表
|
|
@param path 日志文件路径
|
|
@return list
|
|
"""
|
|
file_list = []
|
|
if os.path.exists(path):
|
|
for filename in os.listdir(path):
|
|
if filename.find('.log') == -1: continue
|
|
file_list.append('{}/{}'.format(path,filename))
|
|
|
|
file_list = sorted(file_list,reverse=True)
|
|
return file_list
|
|
|
|
def get_ftp_logs(self,get):
|
|
"""
|
|
@name 获取ftp日志
|
|
"""
|
|
|
|
p,limit,search,username = 1,500,'',''
|
|
if 'p' in get: p = int(get.p)
|
|
if 'limit' in get: limit = int(get.limit)
|
|
if 'search' in get: search = get.search
|
|
if 'username' in get: username = get.username
|
|
|
|
find_idx = 0
|
|
ip_list = []
|
|
log_list = []
|
|
dirs = self.__get_ftp_log_files('{}/ftpServer/Logs'.format(public.get_soft_path()))
|
|
for log_path in dirs:
|
|
|
|
if not os.path.exists(log_path): continue
|
|
if len(log_list) >= limit: break
|
|
|
|
p_num = 0 #分页计数器
|
|
next_file = False
|
|
while not next_file:
|
|
if len(log_list) >= limit:
|
|
break
|
|
p_num += 1
|
|
result = self.GetNumLines(log_path,10001,p_num).split('\r\n')
|
|
if len(result) < 10000:
|
|
next_file = True
|
|
result.reverse()
|
|
for _line in result:
|
|
if not _line.strip(): continue
|
|
if len(log_list) >= limit:
|
|
break
|
|
try:
|
|
if self.find_line_str(_line,search):
|
|
#根据用户名查找
|
|
if username and not re.search(r'-\s+({})\s+\('.format(username),_line):
|
|
continue
|
|
|
|
find_idx += 1
|
|
if find_idx > (p-1) * limit:
|
|
#获取ip归属地
|
|
for _ip in public.get_line_ips(_line):
|
|
if not _ip in ip_list: ip_list.append(_ip)
|
|
|
|
info = escape(_line)
|
|
log_list.append(info)
|
|
except:pass
|
|
|
|
# return self.return_line_area(log_list,ip_list)
|
|
return public.return_message(0, 0, log_list)
|
|
|
|
|
|
#取慢日志
|
|
def get_slow_logs(self,get):
|
|
'''
|
|
@name 获取慢日志
|
|
@get.search 搜索关键字
|
|
'''
|
|
search,p,limit = '',1,1000
|
|
if 'search' in get: search = get.search
|
|
if 'limit' in get: limit = get.limit
|
|
|
|
my_info = public.get_mysql_info()
|
|
if not my_info['datadir']:
|
|
return public.return_message(-1, 0, public.lang("MySQL is not installed!"))
|
|
|
|
path = my_info['datadir'] + '/mysql-slow.log'
|
|
if not os.path.exists(path):
|
|
return public.return_message(-1, 0, public.lang("Log file does not exist!"))
|
|
# mysql慢日志有顺序问题,倒序显示不利于排查问题
|
|
return public.return_message(0, 0, public.xsssec(public.GetNumLines(path, limit)))
|
|
|
|
# find_idx = 0
|
|
# p_num = 0 #分页计数器
|
|
# next_file = False
|
|
# log_list = []
|
|
# while not next_file:
|
|
# if len(log_list) >= limit:
|
|
# break
|
|
# p_num += 1
|
|
# result = self.GetNumLines(path,10001,p_num).replace('\r\n','\n').split('\n')
|
|
# if len(result) < 10000:
|
|
# next_file = True
|
|
# result.reverse()
|
|
|
|
# for _line in result:
|
|
# if not _line: continue
|
|
# if len(log_list) >= limit:
|
|
# break
|
|
|
|
# try:
|
|
# if self.find_line_str(_line,search):
|
|
# find_idx += 1
|
|
# if find_idx > (p-1) * limit:
|
|
# info = escape(_line)
|
|
# log_list.append(info)
|
|
# except:pass
|
|
# return log_list
|
|
|
|
def IP_geolocation(self, get):
|
|
'''
|
|
@name 列出所有IP及其归属地
|
|
@return list {ip: {ip: ip_address, operation_num: 12 ,info: 归属地}, ...]
|
|
'''
|
|
|
|
result = dict()
|
|
|
|
data = public.M('logs').query('''
|
|
select * from logs
|
|
''')
|
|
for arrs in data:
|
|
if not arrs: continue
|
|
end = 0
|
|
# 获得IP的尾后索引
|
|
for ch in arrs[2]:
|
|
if ch.isnumeric() or ch == '.':
|
|
end += 1
|
|
else:
|
|
break
|
|
|
|
ip_addr = arrs[2][0:end]
|
|
|
|
if ip_addr:
|
|
if result.get(ip_addr) != None:
|
|
result[ip_addr]["operation_num"] = result[ip_addr]["operation_num"] + 1
|
|
else:
|
|
result[ip_addr] = {"ip":ip_addr,"operation_num":1, "info":None}
|
|
|
|
return_list = []
|
|
|
|
for k in result:
|
|
info = public.get_free_ip_info(k)
|
|
result[k]["info"] = info["info"]
|
|
return_list.append(result[k])
|
|
|
|
return public.return_message(0, 0, return_list)
|
|
|
|
def get_error_logs_by_search(self, args):
|
|
'''
|
|
@name 根据搜索内容, 获取运行日志中的内容
|
|
@args.search 匹配内容
|
|
@return 匹配该内容的所有日志
|
|
'''
|
|
log_file_path = "{}/logs/error.log".format(public.get_panel_path())
|
|
#return log_file_path
|
|
data = public.readFile(log_file_path)
|
|
if not data:
|
|
return public.return_message(0, 0, None)
|
|
data = data.split('\n')
|
|
result = []
|
|
for line in data:
|
|
if args.search == None:
|
|
result.append(line)
|
|
elif args.search in line:
|
|
result.append(line)
|
|
|
|
return public.return_message(0, 0, result) |