mdserver-web/plugins/task_manager/task_manager_index.py

1642 lines
65 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding:utf-8
import sys
import io
import os
import time
import re
import threading
import psutil
import json
from typing import List, Dict
web_dir = os.getcwd() + "/web"
if os.path.exists(web_dir):
sys.path.append(web_dir)
os.chdir(web_dir)
import core.mw as mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'task_manager'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
class mainClass(object):
pids = None
new_info = {}
old_info = {}
new_net_info = {}
old_net_info = {}
panel_pid = None
task_pid = None
__process_net_list = {}
__cpu_time = None
meter_head = {}
last_net_process = None
last_net_process_time = 0
# lock
_instance_lock = threading.Lock()
is_mac = False
def __init__(self):
# print("__init__")
self.is_mac = mw.isAppleSystem()
self.old_path = getServerDir()+'/task_old.json'
self.old_net_path = getServerDir()+'/network_old.json'
self.old_info['cpu_time'] = self.get_cpu_time()
self.old_info['time'] = time.time()
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(mainClass, "_instance"):
with mainClass._instance_lock:
if not hasattr(mainClass, "_instance"):
mainClass._instance = mainClass(*args, **kwargs)
return mainClass._instance
def get_process_net_list(self):
import copy
w_file = '/dev/shm/mw_net_process'
if not os.path.exists(w_file): return
net_process_body = mw.readFile(w_file)
if not net_process_body: return
net_process = net_process_body.split('\n')
for np in net_process:
if not np: continue
tmp = {}
np_list = np.split()
if len(np_list) < 5: continue
tmp['pid'] = int(np_list[0])
tmp['down'] = int(np_list[1])
tmp['up'] = int(np_list[2])
tmp['down_package'] = int(np_list[3])
tmp['up_package'] = int(np_list[4])
self.__process_net_list[tmp['pid']] = tmp
if time.time() - self.last_net_process_time > 12 or self.last_net_process_time == 0:
self.last_net_process = copy.deepcopy(self.__process_net_list)
self.last_net_process_time = time.time()
# 获取进程连接数
def get_connects(self, pid):
connects = 0
try:
if pid == 1: return connects
tp = '/proc/' + str(pid) + '/fd/'
if not os.path.exists(tp): return connects
for d in os.listdir(tp):
fname = tp + d
if os.path.islink(fname):
l = os.readlink(fname)
if l.find('socket:') != -1: connects += 1
except:
pass
return connects
# 获取进程io写
def get_io_write(self, pid, io_write):
disk_io_write = 0
if not self.old_info: self.old_info = {}
if not pid in self.old_info:
self.old_info[pid] = {}
self.old_info[pid]['io_write'] = io_write
return disk_io_write
if not 'io_write' in self.old_info[pid]:
self.old_info[pid]['io_write'] = io_write
return disk_io_write
io_end = (io_write - self.old_info[pid]['io_write'])
if io_end > 0:
disk_io_write = io_end / (time.time() - self.old_info['time'])
self.old_info[pid]['io_write'] = io_write
if disk_io_write > 0: return int(disk_io_write)
return 0
# 获取io读
def get_io_read(self, pid, io_read):
disk_io_read = 0
if not pid in self.old_info:
self.old_info[pid] = {}
self.old_info[pid]['io_read'] = io_read
return disk_io_read
if not 'io_read' in self.old_info[pid]:
self.old_info[pid]['io_read'] = io_read
return disk_io_read
io_end = (io_read - self.old_info[pid]['io_read'])
if io_end > 0:
disk_io_read = io_end / (time.time() - self.old_info['time'])
self.old_info[pid]['io_read'] = io_read
if disk_io_read > 0: return int(disk_io_read)
return 0
def get_mem_info(self, get=None):
mem = psutil.virtual_memory()
if self.is_mac:
memInfo = {'memTotal': mem.total}
memInfo['memRealUsed'] = memInfo['memTotal'] * (mem.percent / 100)
return memInfo['memRealUsed']
memInfo = {'memTotal': mem.total, 'memFree': mem.free, 'memBuffers': mem.buffers, 'memCached': mem.cached}
memInfo['memRealUsed'] = memInfo['memTotal'] - memInfo['memFree'] - memInfo['memBuffers'] - memInfo['memCached']
return memInfo['memRealUsed']
# 进程备注name,pid,启动命令
def get_process_ps(self, name, pid, p_exe=None, p=None):
processPs = {
'irqbalance': '系统进程-优化系统性能服务',
'containerd': 'docker管理服务',
'qmgr': '系统进程-管理和控制邮件进程',
'pickup': '系统进程-接收和处理待发送的邮件',
'cleanup': '系统进程-服务器释放资源进程',
'trivial-rewrite': '系统进程-邮件重写和转发服务',
'bt-ipfilter': '宝塔网络的IP过滤器',
'oneav': '微步木马检测服务',
'rhsmcertd': '系统进程-验证系统的订阅状态服务',
'tamperuser': '宝塔-企业级防篡改服务',
'lvmetad': '系统进程-元数据守护进程',
'containerd-shim-runc-v2': 'docker容器管理服务',
'tuned': '系统进程-优化系统服务',
'chronyd': '系统进程-时间同步服务',
'auditd': '系统进程-系统安全日志记录服务',
'gssproxy': '系统进程-身份验证和授权服务',
'ossfs': '阿里云对象存储挂载服务',
'cosfs': '腾讯云对象存储挂载服务',
'obsfs': '华为云对象存储挂载服务',
's3fs': '对象存储挂载服务',
'bosfs': '百度云对象存储挂载服务',
'jsvc': 'tomcat服务',
'mysqld': 'MySQL服务',
'php-fpm': 'PHP子进程',
'php-cgi': 'PHP-CGI进程',
'nginx': 'Nginx服务',
'httpd': 'Apache服务',
'sshd': 'SSH服务',
'pure-ftpd': 'FTP服务',
'sftp-server': 'SFTP服务',
'mysqld_safe': 'MySQL服务',
'firewalld': '防火墙服务',
'BT-Panel': '宝塔面板-主进程',
'BT-Task': '宝塔面板-后台任务进程',
'NetworkManager': '网络管理服务',
'svlogd': '日志守护进程',
'memcached': 'Memcached缓存器',
'gunicorn': "python项目",
"BTPanel": '宝塔面板',
'baota_coll': "堡塔云控-主控端",
'baota_client': "堡塔云控-被控端",
'node': 'Node.js程序',
'supervisord': 'Supervisor进程',
'rsyslogd': 'rsyslog日志服务',
'crond': '计划任务服务',
'cron': '计划任务服务',
'rsync': 'rsync文件同步进程',
'ntpd': '网络时间同步服务',
'rpc.mountd': 'NFS网络文件系统挂载服务',
'sendmail': 'sendmail邮件服务',
'postfix': 'postfix邮件服务',
'npm': 'Node.js NPM管理器',
'PM2': 'Node.js PM2进程管理器',
'htop': 'htop进程监控软件',
'btpython': '宝塔面板-独立Python环境进程',
'btappmanagerd': '宝塔应用管理器插件',
'dockerd': 'Docker容器管理器',
'docker-proxy': 'Docker容器管理器',
'docker-registry': 'Docker容器管理器',
'docker-distribution': 'Docker容器管理器',
'docker-network': 'Docker容器管理器',
'docker-volume': 'Docker容器管理器',
'docker-swarm': 'Docker容器管理器',
'docker-systemd': 'Docker容器管理器',
'docker-containerd': 'Docker容器管理器',
'docker-containerd-shim': 'Docker容器管理器',
'docker-runc': 'Docker容器管理器',
'docker-init': 'Docker容器管理器',
'docker-init-systemd': 'Docker容器管理器',
'docker-init-upstart': 'Docker容器管理器',
'docker-init-sysvinit': 'Docker容器管理器',
'docker-init-openrc': 'Docker容器管理器',
'docker-init-runit': 'Docker容器管理器',
'docker-init-systemd-resolved': 'Docker容器管理器',
'rpcbind': 'NFS网络文件系统服务',
'dbus-daemon': 'D-Bus消息总线守护进程',
'systemd-logind': '登录管理器',
'systemd-journald': 'Systemd日志管理服务',
'systemd-udevd': '系统设备管理服务',
'systemd-timedated': '系统时间日期服务',
'systemd-timesyncd': '系统时间同步服务',
'systemd-resolved': '系统DNS解析服务',
'systemd-hostnamed': '系统主机名服务',
'systemd-networkd': '系统网络管理服务',
'systemd-resolvconf': '系统DNS解析服务',
'systemd-local-resolv': '系统DNS解析服务',
'systemd-sysctl': '系统系统参数服务',
'systemd-modules-load': '系统模块加载服务',
'systemd-modules-restore': '系统模块恢复服务',
'agetty': 'TTY登陆验证程序',
'sendmail-mta': 'MTA邮件传送代理',
'bash': 'bash命令行进程',
'(sd-pam)': '可插入认证模块',
'polkitd': '授权管理服务',
'mongod': 'MongoDB数据库服务',
'mongodb': 'MongoDB数据库服务',
'mongodb-mms-monitor': 'MongoDB数据库服务',
'mongodb-mms-backup': 'MongoDB数据库服务',
'mongodb-mms-restore': 'MongoDB数据库服务',
'mongodb-mms-agent': 'MongoDB数据库服务',
'mongodb-mms-analytics': 'MongoDB数据库服务',
'mongodb-mms-tools': 'MongoDB数据库服务',
'mongodb-mms-backup-agent': 'MongoDB数据库服务',
'mongodb-mms-backup-tools': 'MongoDB数据库服务',
'mongodb-mms-restore-agent': 'MongoDB数据库服务',
'mongodb-mms-restore-tools': 'MongoDB数据库服务',
'mongodb-mms-analytics-agent': 'MongoDB数据库服务',
'mongodb-mms-analytics-tools': 'MongoDB数据库服务',
'dhclient': 'DHCP协议客户端',
'dhcpcd': 'DHCP协议客户端',
'dhcpd': 'DHCP服务器',
'isc-dhcp-server': 'DHCP服务器',
'isc-dhcp-server6': 'DHCP服务器',
'dhcp6c': 'DHCP服务器',
'dhcpcd': 'DHCP服务器',
'dhcpd': 'DHCP服务器',
'avahi-daemon': 'Zeroconf守护进程',
'login': '登录进程',
'systemd': '系统管理服务',
'systemd-sysv': '系统管理服务',
'systemd-journal-gateway': '系统管理服务',
'systemd-journal-remote': '系统管理服务',
'systemd-journal-upload': '系统管理服务',
'systemd-networkd': '系统网络管理服务',
'rpc.idmapd': 'NFS网络文件系统相关服务',
'cupsd': '打印服务',
'cups-browsed': '打印服务',
'sh': 'shell进程',
'php': 'PHP CLI模式进程',
'blkmapd': 'NFS映射服务',
'lsyncd': '文件同步服务',
'sleep': '延迟进程'
}
if p_exe:
# print(name.lower(), pid, p_exe)
# if p:
# cmdline = ' '.join(p.cmdline()).strip()
# print(cmdline)
if name == 'php-fpm':
try:
if self.is_mac:
php_version = p_exe.split('/')[-3][3:]
else:
php_version = p_exe.split('/')[-3]
return 'PHP' + php_version + '进程'
except:
pass
elif name.lower() == 'python' or name.lower() == 'python3':
p_exe_arr = p_exe.split('/')
if p_exe_arr[-1] in ['task.py']:
return 'MW面板-后台任务进程'
elif p_exe_arr[-1] in ['BT-Panel', 'runserver.py']:
return '面板-主进程'
elif p_exe.find('process_network_total') != -1:
return '面板-进程网络监控'
if p:
cmdline = ' '.join(p.cmdline()).strip()
cmdline_arr = cmdline.split('/')
if cmdline.find('process_network_total') != -1:
return '进程网络监控'
if cmdline_arr[-1] in ['BT-Task', 'task.py']:
return '后台任务进程'
elif cmdline_arr[-1] in ['BT-Panel', 'runserver.py']:
return '主进程'
elif cmdline.find('process_network_total') != -1:
return '进程网络监控'
elif cmdline.find('tamper_proof_service') != -1:
return '网站防篡改'
elif cmdline.find('syssafe') != -1:
return '系统加固'
elif cmdline.find('opwaf') != -1:
return 'WAF防火墙'
elif cmdline.find('acme') != -1:
return 'SSL证书签发'
elif cmdline.find('psync') != -1:
return '面板一键迁移'
elif cmdline.find('mdserver-web/plugins') != -1:
return '面板插件进程'
elif cmdline.find('/www/server/cron/') != -1:
return '面板计划任务'
elif cmdline.find('task.py') != -1:
return 'MW面板-后台任务'
elif cmdline.find('mdserver-web') != -1 and cmdline.find('gunicorn -c setting.py app:app') != -1:
return 'MW面板'
elif name.lower() == 'gunicorn':
if p:
cmdline = ' '.join(p.cmdline()).strip()
if cmdline.find('mdserver-web') != -1 and cmdline.find('gunicorn -c setting.py app:app') != -1:
return 'MW面板'
elif name == 'nginx':
default_name = 'Nginx'
if p_exe.find('openresty/nginx') != -1:
default_name = 'OpenResty'
if p.username() == 'www':
return default_name+'子进程'
else:
return default_name+'主进程'
elif name == 'openresty':
if p.username() == 'www':
return 'OpenResty子进程'
return 'OpenResty主进程'
elif name == 'mw':
return 'MW面板-命令'
elif p_exe == '/usr/bin/bash':
cmdline = ' '.join(p.cmdline()).strip()
if cmdline.find('task.py') != -1:
return 'MW面板-后台任务'
if cmdline.find('/www/server/cron/') != -1:
return '面板计划任务'
elif cmdline.find('mdserver-web/plugins') != -1:
return '面板插件进程'
if name in processPs: return processPs[name]
# if self.is_panel_process(pid): return 'MW面板'
if p_exe:
exe_keys = {
'/www/server/mdserver-web/plugins/': '面板插件',
'/www/server/cron/': '计划任务进程',
'pm2': 'PM2进程管理器',
'PM2': 'PM2进程管理器',
'nvm': 'NVM Node版本管理器',
'npm': 'NPM Node包管理器'
}
for k in exe_keys.keys():
if p_exe.find(k) != -1: return exe_keys[k]
if name.find(k) != -1: return exe_keys[k]
return name
def get_process_network(self, pid):
if not self.__process_net_list:
self.get_process_net_list()
if not self.last_net_process_time: return 0, 0, 0, 0
if not pid in self.__process_net_list: return 0, 0, 0, 0
if not pid in self.last_net_process:
return self.__process_net_list[pid]['up'], self.__process_net_list[pid]['up_package'], \
self.__process_net_list[pid]['down'], self.__process_net_list[pid]['down_package']
now_t = time.time()
# print(pid, self.__process_net_list[pid]['up'], self.last_net_process[pid]['up'],time.time(),self.last_net_process_time)
up = int((self.__process_net_list[pid]['up'] - self.last_net_process[pid]['up']) / ( now_t - self.last_net_process_time))
down = int((self.__process_net_list[pid]['down'] - self.last_net_process[pid]['down']) / ( now_t - self.last_net_process_time))
up_package = int((self.__process_net_list[pid]['up_package'] - self.last_net_process[pid]['up_package']) / ( now_t - self.last_net_process_time))
down_package = int((self.__process_net_list[pid]['down_package'] - self.last_net_process[pid]['down_package']) / (now_t - self.last_net_process_time))
# print('get_process_network', up, up_package, down, down_package)
return up, up_package, down, down_package
def get_process_cpu_time(self, cpu_times):
cpu_time = 0.00
for s in cpu_times: cpu_time += s
return cpu_time
# 获取cpu使用率
def get_cpu_percent(self, pid, cpu_times, cpu_time):
percent = 0.00
process_cpu_time = self.get_process_cpu_time(cpu_times)
if not self.old_info: self.old_info = {}
if not pid in self.old_info:
self.old_info[pid] = {}
self.old_info[pid]['cpu_time'] = process_cpu_time
return percent
if cpu_time == self.old_info['cpu_time']:
return 0.00
percent = round(100.00 * (process_cpu_time - self.old_info[pid]['cpu_time']) / (cpu_time - self.old_info['cpu_time']), 2)
# self.old_info[pid]['cpu_time'] = process_cpu_time
if percent > 0: return percent
return 0.00
# 获取平均负载
def get_load_average(self):
c = os.getloadavg()
data = {}
data['1'] = round(float(c[0]), 3) # float(c[0])
data['5'] = round(float(c[1]), 3) # float(c[1])
data['15'] = round(float(c[2]), 3) # float(c[2])
return data
def set_meter_head(self, get):
if not 'meter_head_name' in get:
return False
meter_head_name = get['meter_head_name']
meter_head_file = getServerDir()+'/meter_head.json'
try:
self.get_meter_head()
if meter_head_name not in self.meter_head.keys():
return False
if meter_head_name in ['ps', 'memory_used', 'cpu_percent', 'name']:
return False
self.meter_head[meter_head_name] = not self.meter_head[meter_head_name]
mw.writeFile(meter_head_file, json.dumps(self.meter_head))
return True
except:
return False
def get_meter_head(self, get=None):
meter_head_file = getServerDir()+'/meter_head.json'
if os.path.exists(meter_head_file):
self.meter_head = json.loads(mw.readFile(meter_head_file))
else:
self.meter_head = {
'name': True,
'pid': True,
'cpu_percent': True,
'down': True,
'up': True,
'status': True,
'threads': True,
'user': True,
'ps': True,
'memory_used': True,
'io_read_bytes': True,
'io_write_bytes': True,
'connects': True
}
mw.writeFile(meter_head_file, json.dumps(self.meter_head))
return self.meter_head
# 添加进程查找
def search_pro(self, data, search):
try:
ldata = []
for i in data:
if search in i['name'] or search in i['exe'] or search in i['ps'] or search in i[
'user'] or search in str(i['pid']) or search in i['status']:
ldata.append(i)
elif 'children' in i:
for k in i['children']:
if search in k['name'] or search in k['exe'] or search in k['ps'] or search in k[
'user'] or search in str(k['pid']):
ldata.append(i)
return ldata
except:
print(mw.getTracebackInfo())
return data
def get_cpu_time(self):
cpu_times = psutil.cpu_times()
cpu_time = 0.00
for s in cpu_times: cpu_time += s
return cpu_time
# return s.user + s.system + s.nice + s.idle
# 获取python的路径
def get_python_bin(self):
mw_dir = mw.getServerDir() + '/mdserver-web'
bin_file = mw_dir + '/bin/python3'
if os.path.exists(bin_file):
return bin_file
return '/usr/bin/python3'
# 检查process_network_total.py是否运行
def check_process_net_total(self):
mw_dir = mw.getServerDir() + '/mdserver-web'
_pid_file = mw_dir+'/logs/process_network_total.pid'
if os.path.exists(_pid_file):
pid = mw.readFile(_pid_file)
if os.path.exists('/proc/' + pid): return True
cmd_file = mw_dir+'/plugins/task_manager/process_network_total.py'
python_bin = self.get_python_bin()
_cmd = 'nohup {} {} &> /tmp/net.log &'.format(python_bin, cmd_file)
mw.execShell(_cmd)
# 进程折叠,将子进程折叠到父进程下,并将使用资源累加。
def __pro_s_s(self, data: List) -> List:
"""
将子进程合并到父进程中
:param data:进程列表
:return:合并后的进程列表增加children字段
"""
data1 = []
children_set = {'childrens': []}
for i in data:
if i['pid'] > 30 and i['ppid'] == 1:
children = self.__get_children(i['pid'])
s4 = time.time()
if children != []: children_set[i['pid']] = children
children_set['childrens'] += children
for i in data:
if i['pid'] in children_set:
i['children'] = []
for j in data:
if j['pid'] in children_set[i['pid']]:
i['children'].append(j)
i['memory_used'] += j['memory_used']
i['cpu_percent'] = round(i['cpu_percent'] + j['cpu_percent'], 2)
i['connects'] += j['connects']
i['threads'] += j['threads']
if 'io_write_bytes' in j:
i['io_write_bytes'] += j['io_write_bytes']
if 'io_read_bytes' in j:
i['io_read_bytes'] += j['io_read_bytes']
if 'io_write_speed' in j:
i['io_write_speed'] += j['io_write_speed']
if 'io_read_speed' in j:
i['io_read_speed'] += j['io_read_speed']
if 'up' in j:
i['up'] += j['up']
if 'up_package' in j:
i['up_package'] += j['up_package']
if 'down' in j:
i['down'] += j['down']
if 'down_package' in j:
i['down_package'] += j['down_package']
data1.append(i)
elif i['pid'] not in children_set['childrens']:
data1.append(i)
return data1
def __get_children(self, pid: int) -> List:
try:
p = psutil.Process(pid) # pid为指定进程的进程号
psutil.process_iter()
children = p.children(recursive=True) # 获取指定进程的所有子进程
pids = []
for child in children:
pids.append(child.pid)
return pids
except:
return []
# 外部接口结束进程pid30以上
def kill_process(self, get):
pid = int(get['pid'])
if pid < 30: return mw.returnData(False, '不能结束系统关键进程!')
if not pid in psutil.pids(): return mw.returnData(False, '指定进程不存在!')
if not 'killall' in get:
p = psutil.Process(pid)
if self.is_panel_process(pid): return mw.returnData(False, '不能结束面板服务进程')
p.kill()
return mw.returnData(True, '进程已结束')
return self.kill_process_all(pid)
# 是否为面板进程
def is_panel_process(self, pid):
if not self.panel_pid:
self.panel_pid = os.getpid()
if pid == self.panel_pid: return True
if not self.task_pid:
try:
self.task_pid = int(mw.execShell("ps -ef | grep 'python3 task.py' |grep -v grep|head -n1|awk '{print $2}'")[0])
except:
self.task_pid = -1
if pid == self.task_pid: return True
return False
# 遍历结束pid的子进程 kill_process_all——>引用kill_process_lower
def kill_process_lower(self, pid):
pids = psutil.pids()
for lpid in pids:
if lpid < 30: continue
if self.is_panel_process(lpid): continue
p = psutil.Process(lpid)
ppid = p.ppid()
if ppid == pid:
p.kill()
return self.kill_process_lower(lpid)
return True
# 结束进程树 kill_process——>引用kill_process_all
def kill_process_all(self, pid):
if pid < 30: return mw.returnData(True, '已结束此进程树!')
if self.is_panel_process(pid): return mw.returnData(False, '不能结束面板服务进程')
try:
if not pid in psutil.pids(): mw.returnData(True, '已结束此进程树!')
p = psutil.Process(pid)
ppid = p.ppid()
name = p.name()
p.kill()
mw.execShell('pkill -9 ' + name)
if name.find('php-') != -1:
mw.execShell("rm -f /tmp/php-cgi-*.sock")
elif name.find('mysql') != -1:
mw.execShell("rm -f /tmp/mysql.sock")
elif name.find('nginx') != -1:
mw.execShell("rm -f /tmp/mysql.sock")
self.kill_process_lower(pid)
if ppid: return self.kill_process_all(ppid)
except:
pass
return mw.returnData(True, '已结束此进程树!')
def get_process_list(self, args = {}):
# https://hellowac.github.io/psutil-doc-zh/processes/process_class/oneshot.html
if self.is_mac:
return self.get_process_list_mac(args)
return self.get_process_list_linux(args)
def get_process_list_mac(self, args = {}):
self.new_info['cpu_time'] = self.get_cpu_time()
self.new_info['time'] = time.time()
sortx = 'all'
if 'sortx' in args: sortx = args['sortx']
if not 'sortx' in args:
args['sortx'] = 'status'
if args['sortx'] == 'status': res = False
if 'reverse' in args:
if args['reverse'] in ['undefined', 'null']:
args['reverse'] = 'True'
args['sortx'] = 'all'
if not args['reverse'] in ['True', 'False']: args['reverse'] = 'True'
res_list = {'True': True, 'False': False}
res = res_list[args['reverse']]
else:
args['reverse'] = True
if args['reverse'] in ['undefined', 'null']:
args['reverse'] = 'True'
args['sortx'] = 'all'
info = {}
info['activity'] = 0
info['cpu'] = 0.00
info['mem'] = 0
info['disk'] = 0
status_ps = {'sleeping': '睡眠', 'running': '活动'}
ppids = psutil.pids()
processList = []
for pid in ppids:
tmp = {}
try:
try:
p = psutil.Process(pid)
except Exception as e:
continue
with p.oneshot():
p_state = p.status()
try:
tmp['exe'] = p.exe()
except Exception as e:
continue
tmp['name'] = p.name()
tmp['pid'] = pid
tmp['ppid'] = p.ppid()
tmp['create_time'] = int(p.create_time())
tmp['status'] = p_state
tmp['user'] = p.username()
tmp['connects'] = self.get_connects(pid)
if p_state == 'running': info['activity'] += 1
if p_state in status_ps: p_state = status_ps[p_state]
try:
tmp['threads'] = p.num_threads()
except Exception as e:
continue
tmp['ps'] = self.get_process_ps(tmp['name'], pid, tmp['exe'], p)
tmp['up'], tmp['up_package'], tmp['down'], tmp['down_package'] = self.get_process_network(pid)
try:
p_cpus = p.cpu_times()
except Exception as e:
continue
try:
p_mem = p.memory_info()
except Exception as e:
continue
if p_mem.rss == 0: continue
tmp['memory_used'] = p_mem.rss
tmp['cpu_percent'] = self.get_cpu_percent(str(pid), p_cpus, self.new_info['cpu_time'])
# print(tmp['cpu_percent'])
if tmp['cpu_percent'] > 100: tmp['cpu_percent'] = 0.1
info['cpu'] += tmp['cpu_percent']
info['disk'] += 0
processList.append(tmp)
del (p)
del (tmp)
except Exception as e:
print("err:", mw.getTracebackInfo())
continue
processList = self.__pro_s_s(processList)
res = True
if args['sortx'] not in ['all']:
processList = sorted(processList, key=lambda x: x[args['sortx']], reverse=res)
else:
processList = sorted(processList, key=lambda x: [x['cpu_percent'], x['connects'], x['threads'],
x['memory_used']], reverse=res)
info['load_average'] = self.get_load_average()
data = {}
data['is_mac'] = self.is_mac
data['process_list'] = processList
info['cpu'] = round(info['cpu'], 3)
info['mem'] = self.get_mem_info()
data['info'] = info
if 'search' in args:
if args['search'] != '':
data['process_list'] = self.search_pro(data['process_list'], args['search'])
self.get_meter_head()
data['meter_head'] = self.meter_head
data['meter_head']['io_read_bytes'] = False
data['meter_head']['io_write_bytes'] = False
data['meter_head']['down'] = False
data['meter_head']['up'] = False
return data
# 获取进程信息
def get_process_list_linux(self, get = {}):
self.check_process_net_total()
self.pids = psutil.pids()
processList = []
if type(self.new_info) != dict: self.new_info = {}
self.new_info['cpu_time'] = self.get_cpu_time()
self.new_info['time'] = time.time()
self.get_process_net_list()
if not 'sortx' in get:
get['sortx'] = 'all'
res = True
if get['sortx'] == 'status':
res = False
if 'reverse' in get:
if get['reverse'] in ['undefined', 'null']:
get['reverse'] = 'True'
get['sortx'] = 'all'
if not get['reverse'] in ['True', 'False']: get['reverse'] = 'True'
res_list = {'True': True, 'False': False}
res = res_list[get['reverse']]
else:
get['reverse'] = True
if get['reverse'] in ['undefined', 'null']:
get['reverse'] = 'True'
get['sortx'] = 'all'
info = {}
info['activity'] = 0
info['cpu'] = 0.00
info['mem'] = 0
info['disk'] = 0
status_ps = {'sleeping': '睡眠', 'running': '活动'}
for pid in self.pids:
tmp = {}
try:
try:
p = psutil.Process(pid)
except Exception as e:
continue
with p.oneshot():
try:
p_mem = p.memory_full_info()
except Exception as e:
continue
if p_mem.rss == 0: continue
pio = p.io_counters()
p_cpus = p.cpu_times()
p_state = p.status()
if p_state == 'running': info['activity'] += 1
if p_state in status_ps: p_state = status_ps[p_state]
tmp['exe'] = p.exe()
try:
tmp['name'] = p.name()
except Exception as e:
continue
tmp['pid'] = pid
tmp['ppid'] = p.ppid()
tmp['create_time'] = int(p.create_time())
tmp['status'] = p_state
tmp['user'] = p.username()
tmp['memory_used'] = p_mem.uss
tmp['cpu_percent'] = self.get_cpu_percent(str(pid), p_cpus, self.new_info['cpu_time'])
if tmp['name'] == 'BT-Panel' and tmp['cpu_percent'] > 1:
tmp['cpu_percent'] = round(tmp['cpu_percent'] % 1, 2)
tmp['io_write_bytes'] = pio.write_bytes
tmp['io_read_bytes'] = pio.read_bytes
tmp['io_write_speed'] = self.get_io_write(str(pid), pio.write_bytes)
tmp['io_read_speed'] = self.get_io_read(str(pid), pio.read_bytes)
tmp['connects'] = self.get_connects(pid)
tmp['threads'] = p.num_threads()
tmp['ps'] = self.get_process_ps(tmp['name'], pid, tmp['exe'], p)
tmp['up'], tmp['up_package'], tmp['down'], tmp['down_package'] = self.get_process_network(pid)
# print(pid,tmp['up'], tmp['up_package'], tmp['down'], tmp['down_package'])
if tmp['cpu_percent'] > 100: tmp['cpu_percent'] = 0.1
info['cpu'] += tmp['cpu_percent']
info['disk'] += tmp['io_write_speed'] + tmp['io_read_speed']
processList.append(tmp)
del (p)
del (tmp)
except Exception as e:
print(mw.getTracebackInfo())
continue
processList = self.__pro_s_s(processList)
if get['sortx'] not in ['all']:
processList = sorted(processList, key=lambda x: x[get['sortx']], reverse=res)
else:
processList = sorted(processList, key=lambda x: [x['cpu_percent'], x['up'], x['down'], x['io_write_speed'],
x['io_read_speed'], x['connects'], x['threads'],
x['memory_used']], reverse=res)
info['load_average'] = self.get_load_average()
data = {}
data['process_list'] = processList
info['cpu'] = round(info['cpu'], 2)
info['mem'] = self.get_mem_info()
data['info'] = info
if 'search' in get:
if get['search'] != '':
data['process_list'] = self.search_pro(data['process_list'], get['search'])
self.get_meter_head()
data['meter_head'] = self.meter_head
return data
def object_to_dict(self, obj):
result = {}
for name in dir(obj):
value = getattr(obj, name)
if not name.startswith('__') and not callable(value) and not name.startswith('_'): result[name] = value
return result
def list_to_dict(self, data):
result = []
for s in data:
result.append(self.object_to_dict(s))
return result
# 获取进程的详细信息
def get_process_info(self, args={}):
pid = int(args['pid'])
try:
p = psutil.Process(pid)
processInfo = {}
if self.is_mac:
p_mem = self.object_to_dict(p.memory_info())
else:
p_mem = self.object_to_dict(p.memory_full_info())
pio = p.io_counters()
processInfo['io_write_bytes'] = pio.write_bytes;
processInfo['io_read_bytes'] = pio.read_bytes;
# p_cpus= p.cpu_times()
processInfo['exe'] = p.exe()
processInfo['name'] = p.name();
processInfo['pid'] = pid;
processInfo['ppid'] = p.ppid()
processInfo['pname'] = 'sys'
if processInfo['ppid'] != 0: processInfo['pname'] = psutil.Process(processInfo['ppid']).name()
processInfo['comline'] = p.cmdline()
processInfo['create_time'] = int(p.create_time())
processInfo['open_files'] = self.list_to_dict(p.open_files())
processInfo['status'] = p.status();
processInfo['user'] = p.username();
processInfo['memory_full'] = p_mem
processInfo['connects'] = self.get_connects(pid)
processInfo['threads'] = p.num_threads()
processInfo['ps'] = self.get_process_ps(processInfo['name'], pid, processInfo['exe'], p)
except Exception as e:
# print(mw.getTracebackInfo())
return mw.returnData(False, '指定进程已关闭!')
return processInfo
# 获取用户组处理函数 get_user_list——>引用get_group_name
def get_group_name(self, gid):
for g in self.groupList:
if g['gid'] == gid: return g['group']
return ''
# 用户名注释ps get_user_list——>引用get_user_ps
def get_user_ps(self, name, ps):
userPs = {'www': '面板', 'root': '超级管理员', 'mysql': '用于运行MySQL的用户',
'mongo': '用于运行MongoDB的用户',
'git': 'git用户', 'mail': 'mail', 'nginx': '第三方nginx用户', 'postfix': 'postfix邮局用户',
'lp': '打印服务帐号',
'daemon': '控制后台进程的系统帐号', 'nobody': '匿名帐户', 'bin': '管理大部分命令的帐号',
'adm': '管理某些管理文件的帐号', 'smtp': 'smtp邮件'}
if name in userPs: return userPs[name]
if not ps: return name
return ps
# 获取服务器的组名和id从/etc/group中读取。存储到self.groupList,get_user_list——>引用get_group_list
def get_group_list(self, get):
tmpList = mw.readFile('/etc/group').split("\n")
groupList = []
for gl in tmpList:
tmp = gl.split(':')
if len(tmp) < 3: continue
groupInfo = {}
groupInfo['group'] = tmp[0]
groupInfo['gid'] = tmp[2]
groupList.append(groupInfo)
return groupList;
# 外部接口,删除用户,不能删除系统运行环境用户
def remove_user(self, get):
if self.is_mac:
return mw.returnData(False, '无法操作!')
users = ['www', 'root', 'mysql', 'shutdown', 'postfix',
'smmsp', 'sshd', 'systemd-network', 'systemd-bus-proxy',
'avahi-autoipd', 'mail', 'sync', 'lp',
'adm', 'bin', 'mailnull', 'ntp', 'daemon', 'sys'];
if not 'user' in get:
return mw.returnData(False, '缺少参数!')
if get['user'] in users: return mw.returnData(False, '不能删除系统和环境关键用户!')
user = get['user']
r = mw.execShell("userdel " + user)
if r[1].find('process') != -1:
try:
pid = r[1].split()[-1]
p = psutil.Process(int(pid))
pname = p.name()
p.kill()
mw.execShell("pkill -9 " + pname)
r = mw.execShell("userdel " + user)
except:
pass
if r[1].find('userdel:') != -1: return mw.returnData(False, r[1]);
return mw.returnData(True, '删除成功!')
# 获取用户列表 从/etc/passwd文件中读取
def get_user_list(self, get={}):
tmpList = mw.readFile('/etc/passwd').strip().split("\n")
userList = []
self.groupList = self.get_group_list(get)
for ul in tmpList:
tmp = ul.split(':')
if len(tmp) < 6: continue
userInfo = {}
userInfo['username'] = tmp[0]
userInfo['uid'] = tmp[2]
userInfo['gid'] = tmp[3]
userInfo['group'] = self.get_group_name(tmp[3])
userInfo['ps'] = self.get_user_ps(tmp[0], tmp[4])
userInfo['home'] = tmp[5]
userInfo['login_shell'] = tmp[6]
userList.append(userInfo)
# print(userList)
if 'search' in get:
if get['search'] != '':
userList = self.search_user(userList, get['search'])
return userList
# 查询用户
def search_user(self, data, search):
try:
ldata = []
for i in data:
if search in i['username'] or search in i['ps'] or search in i['login_shell'] or search in i[
'home'] or search in i['group']:
ldata.append(i)
return ldata
except:
mw.writeLog('任务管理', traceback.format_exc())
return data
# get_network_list ——>引用get_network
def get_network(self):
try:
networkIo = psutil.net_io_counters()[:4]
self.new_net_info['upTotal'] = networkIo[0]
self.new_net_info['downTotal'] = networkIo[1]
self.new_net_info['upPackets'] = networkIo[2]
self.new_net_info['downPackets'] = networkIo[3]
self.new_net_info['time'] = time.time()
if not self.old_net_info: self.old_net_info = {}
if not 'upTotal' in self.old_net_info:
time.sleep(0.1)
networkIo = psutil.net_io_counters()[:4]
self.old_net_info['upTotal'] = networkIo[0]
self.old_net_info['downTotal'] = networkIo[1]
self.old_net_info['upPackets'] = networkIo[2]
self.old_net_info['downPackets'] = networkIo[3]
self.old_net_info['time'] = time.time()
s = self.new_net_info['time'] - self.old_net_info['time']
networkInfo = {}
networkInfo['upTotal'] = networkIo[0]
networkInfo['downTotal'] = networkIo[1]
networkInfo['up'] = round((float(networkIo[0]) - self.old_net_info['upTotal']) / s, 2)
networkInfo['down'] = round((float(networkIo[1]) - self.old_net_info['downTotal']) / s, 2)
networkInfo['downPackets'] = networkIo[3]
networkInfo['upPackets'] = networkIo[2]
networkInfo['downPackets_s'] = int((networkIo[3] - self.old_net_info['downPackets']) / s)
networkInfo['upPackets_s'] = int((networkIo[2] - self.old_net_info['upPackets']) / s)
return networkInfo
except:
return None
# 获取当前网络连接信息
def get_network_list(self, get = {}):
netstats = psutil.net_connections()
data = {}
data['is_mac'] = False
if self.is_mac:
data['is_mac'] = self.is_mac
return data
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()
if tmp['process'] in ['gunicorn']: continue
tmp['pid'] = netstat.pid
networkList.append(tmp)
del (p)
del (tmp)
networkList = sorted(networkList, key=lambda x: x['status'], reverse=True)
data['list'] = networkList
data['state'] = self.get_network()
if 'search' in get:
if get['search'] != '':
data['list'] = self.search_network(data['list'], get['search'])
return data
# 查询网络
def search_network(self, data, search):
try:
ldata = []
for i in data:
if search in i['process'] or search in i['status'] or search in str(i['pid']) or search in i['laddr'][
0] or search in str(
i['laddr'][1]):
ldata.append(i)
continue
if i['raddr'] != 'NONE':
for j in i['raddr']:
if search in str(j):
ldata.append(i)
return ldata
except:
return data
# 获取当前运行级别 get_service_list ——> 引用get_my_runlevel
def get_my_runlevel(self):
try:
runlevel = mw.execShell('runlevel')[0].split()[1]
except:
runlevel_dict = {"multi-user.target": '3', 'rescue.target': '1', 'poweroff.target': '0',
'graphical.target': '5', "reboot.target": '6'}
r_tmp = mw.execShell('systemctl get-default')[0].strip()
if r_tmp in runlevel_dict:
runlevel = runlevel_dict[r_tmp]
else:
runlevel = '3'
return runlevel
# 服务注释 get_service_list——>引用 get_run_ps
def get_run_ps(self, name):
runPs = {'netconsole': '网络控制台日志', 'network': '网络服务', 'jexec': 'JAVA', 'tomcat8': 'Apache Tomcat',
'tomcat7': 'Apache Tomcat', 'mariadb': 'Mariadb',
'tomcat9': 'Apache Tomcat', 'tomcat': 'Apache Tomcat', 'memcached': 'Memcached缓存器',
'php-fpm-53': 'PHP-5.3', 'php-fpm-52': 'PHP-5.2',
'php-fpm-54': 'PHP-5.4', 'php-fpm-55': 'PHP-5.5', 'php-fpm-56': 'PHP-5.6', 'php-fpm-70': 'PHP-7.0',
'php-fpm-71': 'PHP-7.1',
'php-fpm-72': 'PHP-7.2', 'rsync_inotify': 'rsync实时同步', 'pure-ftpd': 'FTP服务',
'mongodb': 'MongoDB', 'nginx': 'Web服务器(Nginx)',
'httpd': 'Web服务器(Apache)', 'mw': '面板', 'mysqld': 'MySQL数据库', 'rsynd': 'rsync主服务',
'php-fpm': 'PHP服务', 'systemd': '系统核心服务',
'/etc/rc.local': '用户自定义启动脚本', '/etc/profile': '全局用户环境变量',
'/etc/inittab': '用于自定义系统运行级别', '/etc/rc.sysinit': '系统初始化时调用的脚本',
'sshd': 'SSH服务', 'crond': '计划任务服务', 'udev-post': '设备管理系统', 'auditd': '审核守护进程',
'rsyslog': 'rsyslog服务', 'sendmail': '邮件发送服务', 'blk-availability': 'lvm2相关',
'local': '用户自定义启动脚本', 'netfs': '网络文件系统', 'lvm2-monitor': 'lvm2相关',
'xensystem': 'xen云平台相关', 'iptables': 'iptables防火墙', 'ip6tables': 'iptables防火墙 for IPv6',
'firewalld': 'firewall防火墙'}
if name in runPs: return runPs[name]
return name
# 清除注释
def clear_comments(self, body):
bodyTmp = body.split("\n")
bodyR = ""
for tmp in bodyTmp:
if tmp.startswith('#'): continue
if tmp.strip() == '': continue
bodyR += tmp
return bodyR
# 获取启动项
def get_run_list(self, get={}):
data = {}
data['is_mac'] = False
if self.is_mac:
data['is_mac'] = self.is_mac
return data
runFile = ['/etc/rc.local', '/etc/profile', '/etc/inittab', '/etc/rc.sysinit']
runList = []
for rfile in runFile:
if not os.path.exists(rfile): continue
bodyR = self.clear_comments(mw.readFile(rfile))
if not bodyR: continue
stat = os.stat(rfile)
accept = str(oct(stat.st_mode)[-3:])
if accept == '644': continue
tmp = {}
tmp['name'] = rfile
tmp['srcfile'] = rfile
tmp['size'] = os.path.getsize(rfile)
tmp['access'] = accept
tmp['ps'] = self.get_run_ps(rfile)
# tmp['body'] = bodyR
runList.append(tmp)
runlevel = self.get_my_runlevel()
runPath = ['/etc/init.d', '/etc/rc' + runlevel + '.d']
tmpAll = []
islevel = False
for rpath in runPath:
if not os.path.exists(rpath): continue
if runPath[1] == rpath: islevel = True
for f in os.listdir(rpath):
if f[:1] != 'S': continue
filename = rpath + '/' + f
if not os.path.exists(filename): continue
if os.path.isdir(filename): continue
if os.path.islink(filename):
flink = os.readlink(filename).replace('../', '/etc/')
if not os.path.exists(flink): continue
filename = flink
tmp = {}
tmp['name'] = f
if islevel: tmp['name'] = f[3:]
if tmp['name'] in tmpAll: continue
stat = os.stat(filename)
accept = str(oct(stat.st_mode)[-3:])
if accept == '644': continue
tmp['srcfile'] = filename
tmp['access'] = accept
tmp['size'] = os.path.getsize(filename)
tmp['ps'] = self.get_run_ps(tmp['name'])
runList.append(tmp)
tmpAll.append(tmp['name'])
data = {}
data['run_list'] = runList
data['run_level'] = runlevel
if 'search' in get:
if get['search'] != '':
data['run_list'] = self.search_run(data['run_list'], get['search'])
return data
# 检查服务是否为系统服务get_systemctl_list——>引用cont_systemctl
def cont_systemctl(self, name):
conts = ['systemd', 'rhel', 'plymouth', 'rc-', '@', 'init', 'ipr', 'dbus', '-local']
for c in conts:
if name.find(c) != -1: return False
return True
# 获取系统服务运行级别 get_service_list——>引用get_systemctl_list
def get_systemctl_list(self, serviceList, runlevel):
systemctl_user_path = '/usr/lib/systemd/system/'
systemctl_run_path = '/etc/systemd/system/multi-user.target.wants/'
if not os.path.exists(systemctl_user_path) or not os.path.exists(systemctl_run_path): return serviceList
r = '.service'
for d in os.listdir(systemctl_user_path):
if d.find(r) == -1: continue;
if not self.cont_systemctl(d): continue;
isrun = '<span style="color:red;" title="点击开启">关闭</span>'
serviceInfo = {}
serviceInfo['name'] = d.replace(r, '')
serviceInfo['runlevel_0'] = isrun
serviceInfo['runlevel_1'] = isrun
serviceInfo['runlevel_2'] = isrun
serviceInfo['runlevel_3'] = isrun
serviceInfo['runlevel_4'] = isrun
serviceInfo['runlevel_5'] = isrun
serviceInfo['runlevel_6'] = isrun
if os.path.exists(systemctl_run_path + d):
isrun = '<span style="color:green;" title="点击关闭">开启</span>'
serviceInfo['runlevel_' + runlevel] = isrun
serviceInfo['runlevel_3'] = isrun
serviceInfo['runlevel_5'] = isrun
serviceInfo['ps'] = self.get_run_ps(serviceInfo['name'])
serviceList.append(serviceInfo)
return serviceList
# 外部接口删除服务。不能删除mw
def remove_service(self, get):
if not 'serviceName' in get:
return mw.returnData(False,'缺少参数');
serviceName = get['serviceName']
if serviceName == 'mw': return mw.returnData(False, '不能通过面板结束面板服务!')
systemctl_user_path = '/usr/lib/systemd/system/'
if os.path.exists(systemctl_user_path + serviceName + '.service'):
return mw.returnData(False,'Systemctl托管的服务不能通过面板删除');
mw.execShell('service ' + serviceName + ' stop')
if os.path.exists('/usr/sbin/update-rc.d'):
mw.execShell('update-rc.d ' + serviceName + ' remove')
elif os.path.exists('/usr/sbin/chkconfig'):
mw.execShell('chkconfig --del ' + serviceName)
else:
mw.execShell("rm -f /etc/rc0.d/*" + serviceName)
mw.execShell("rm -f /etc/rc1.d/*" + serviceName)
mw.execShell("rm -f /etc/rc2.d/*" + serviceName)
mw.execShell("rm -f /etc/rc3.d/*" + serviceName)
mw.execShell("rm -f /etc/rc4.d/*" + serviceName)
mw.execShell("rm -f /etc/rc5.d/*" + serviceName)
mw.execShell("rm -f /etc/rc6.d/*" + serviceName)
filename = '/etc/init.d/' + serviceName
if os.path.exists(filename): os.remove(filename)
return mw.returnData(True, '删除成功!')
# 外部接口设置软件运行环境不能设置06
def set_runlevel_state(self, get):
if not 'runlevel' in get:
return mw.returnData(False,'缺少参数[runlevel]')
if not 'serviceName' in get:
return mw.returnData(False,'缺少参数[serviceName]')
runlevel = get['runlevel']
serviceName = get['serviceName']
if runlevel == '0' or runlevel == '6':
return mw.returnData(False,'为安全考虑,不能通过面板直接修改此运行级别')
systemctl_user_path = '/usr/lib/systemd/system/'
systemctl_run_path = '/etc/systemd/system/multi-user.target.wants/'
if os.path.exists(systemctl_user_path + serviceName + '.service'):
runlevel_cmd = mw.execShell('runlevel')[0].split()[1]
if runlevel_cmd != runlevel:
return mw.returnData(False,'Systemctl托管的服务不能设置非当前运行级别的状态')
action = 'enable'
if os.path.exists(systemctl_run_path + serviceName + '.service'):
action = 'disable'
mw.execShell('systemctl ' + action + ' ' + serviceName + '.service')
return mw.returnData(True, '设置成功!')
rc_d = '/etc/rc' + runlevel + '.d/'
import shutil
for d in os.listdir(rc_d):
if d[3:] != serviceName: continue
sfile = rc_d + d
c = 'S'
if d[:1] == 'S': c = 'K'
dfile = rc_d + c + d[1:]
shutil.move(sfile, dfile)
return mw.returnData(True, '设置成功!')
return mw.returnData(False, '设置失败!')
# 外部接口 查询服务启动级别 /etc/init.d/
def get_service_list(self, get = {}):
data = {}
data['is_mac'] = False
if self.is_mac:
data['is_mac'] = self.is_mac
return data
init_d = '/etc/init.d/'
serviceList = []
for sname in os.listdir(init_d):
try:
if str(oct(os.stat(init_d + sname).st_mode)[-3:]) == '644': continue
serviceInfo = {}
runlevels = self.get_runlevel(sname)
serviceInfo['name'] = sname
serviceInfo['runlevel_0'] = runlevels[0]
serviceInfo['runlevel_1'] = runlevels[1]
serviceInfo['runlevel_2'] = runlevels[2]
serviceInfo['runlevel_3'] = runlevels[3]
serviceInfo['runlevel_4'] = runlevels[4]
serviceInfo['runlevel_5'] = runlevels[5]
serviceInfo['runlevel_6'] = runlevels[6]
serviceInfo['ps'] = self.get_run_ps(sname)
serviceList.append(serviceInfo)
except:
continue
data['runlevel'] = self.get_my_runlevel()
data['serviceList'] = sorted(serviceList, key=lambda x: x['name'], reverse=False)
data['serviceList'] = self.get_systemctl_list(data['serviceList'], data['runlevel'])
if 'search' in get:
if get['search'] != '':
data['serviceList'] = self.search_service(data['serviceList'], get['search'])
return data
def search_service(self, data, search):
try:
ldata = []
for i in data:
if search in i['name'] or search in i['ps']:
ldata.append(i)
return ldata
except:
return data
# 获取存放计划任务的路径
def get_cron_file(self):
filename = '/var/spool/cron/crontabs/root'
if os.path.exists(filename): return filename
filename = '/var/spool/cron/root'
if not os.path.exists(filename):
mw.writeFile(filename, "")
return filename
# 数转周
def toWeek(self, num):
if num > 6: return ''
wheres = {
0: '',
1: '',
2: '',
3: '',
4: '',
5: '',
6: '',
}
return wheres[num]
# 解析计划任务执行周期
def decode_cron_cycle(self, tmp):
if not tmp[4]: tmp[4] = '*'
if tmp[4] != '*':
cycle = '每周' + self.toWeek(int(tmp[4])) + '' + tmp[1] + '' + tmp[0] + ''
elif tmp[2] != '*':
if tmp[2].find('*') == -1:
cycle = '每月的' + tmp[2] + '日,' + tmp[1] + '' + tmp[0] + ''
else:
cycle = '每隔' + tmp[2].split('/')[1] + '' + tmp[1] + '' + tmp[0] + ''
elif tmp[1] != '*':
if tmp[1].find('*') == -1:
cycle = '每天的' + tmp[1] + '' + tmp[0] + ''
else:
cycle = '每隔' + tmp[1].split('/')[1] + '小时' + tmp[0] + '分钟'
elif tmp[0] != '*':
if tmp[0].find('*') == -1:
cycle = '每小时的第' + tmp[0] + '分钟'
else:
cycle = '每隔' + tmp[0].split('/')[1] + '分钟'
else:
return None
return cycle
# 添加计划任务备注
def decode_cron_connand(self, tmp):
command = ''
for i in range(len(tmp)):
if i < 5: continue
command += tmp[i] + ' '
ps = '未知任务'
if command.find('/www/server/cron') != -1:
ps = '通过面板添加的计划任务'
elif command.find('.acme.sh') != -1:
ps = '基于acme.sh的证书续签任务'
elif command.find('certbot-auto renew') != -1:
ps = '基于certbot的证书续签任务'
tmpScript = command.split('>')[0].strip()
filename = tmpScript.replace('"', '').split()[0]
# if not os.path.exists(filename): filename = '';
return command.strip(), ps, filename
# 外部接口,获取计划任务列表
def get_cron_list(self, get = {}):
filename = self.get_cron_file()
cronList = []
if not os.path.exists(filename):
return cronList
tmpList = mw.readFile(filename).split("\n")
for c in tmpList:
c = c.strip()
if c.startswith('#'): continue
tmp = c.split(' ')
if len(tmp) < 6: continue
cronInfo = {}
cronInfo['cycle'] = self.decode_cron_cycle(tmp)
if not cronInfo['cycle']: continue
ctmp = self.decode_cron_connand(tmp)
cronInfo['command'] = c
cronInfo['ps'] = ctmp[1]
cronInfo['exe'] = ctmp[2]
cronInfo['test'] = ctmp[0]
cronList.append(cronInfo)
if 'search' in get:
if get['search'] != '':
cronList = self.search_cron(cronList, get['search'])
return cronList
def search_cron(self, data, search):
try:
ldata = []
for i in data:
if search in i['command'] or search in i['cycle'] or search in i['ps']:
ldata.append(i)
return ldata
except:
return data
# 重启cron服务
def crondReload(self):
if os.path.exists('/etc/init.d/crond'):
mw.execShell('/etc/init.d/crond reload')
elif os.path.exists('/etc/init.d/cron'):
mw.execShell('service cron restart')
else:
mw.execShell("systemctl reload crond")
# 外部接口,删除计划任务
def remove_cron(self, get):
if not 'index' in get:
return mw.returnData(False, '参数不存在[index]!')
index = int(get['index'])
cronList = self.get_cron_list({})
if index > len(cronList) + 1: return mw.returnData(False, '指定任务不存在!')
toCron = []
for i in range(len(cronList)):
if i == index: continue
toCron.append(cronList[i]['command'])
cronStr = "\n".join(toCron) + "\n\n"
filename = self.get_cron_file()
mw.writeFile(filename, cronStr)
mw.execShell("chmod 600 " + filename)
self.crondReload()
return mw.returnData(True, '删除成功!')
# 外部接口 强制结束会话
def pkill_session(self, get= {}):
if not 'pts' in get:
return mw.returnData(False, '缺少参数!')
mw.execShell("pkill -kill -t " + get['pts'])
return mw.returnData(True, '已强行结束会话[' + get['pts'] + ']')
# 获取当前会话
def get_who(self, get = {}):
whoTmp = mw.execShell('who')[0]
tmpList = whoTmp.split("\n")
whoList = []
for w in tmpList:
tmp = w.split()
if len(tmp) < 5: continue
whoInfo = {}
whoInfo['user'] = tmp[0]
whoInfo['pts'] = tmp[1]
whoInfo['date'] = tmp[2] + ' ' + tmp[3]
whoInfo['ip'] = tmp[4].replace('(', '').replace(')', '')
if len(tmp) > 5:
whoInfo['date'] = tmp[2] + ' ' + tmp[3] + ' ' + tmp[4]
whoInfo['ip'] = tmp[5].replace('(', '').replace(')', '')
whoList.append(whoInfo)
if hasattr(get, 'search'):
if get.search != '':
whoList = self.search_who(whoList, get.search)
return whoList
def test_cpu(self):
pid = 43046
p = psutil.Process(pid)
tmp = {}
self.new_info['cpu_time'] = self.get_cpu_time()
self.new_info['time'] = time.time()
with p.oneshot():
p_cpus = p.cpu_times()
print(p_cpus)
tmp['cpu_percent'] = self.get_cpu_percent(str(pid), p_cpus, self.new_info['cpu_time'])
print(tmp['cpu_percent'])
def get_network_list(args = {}):
return mainClass.instance().get_network_list(args)
def get_process_list(args = {}):
try:
return mainClass.instance().get_process_list(args)
except Exception as e:
return str(e)
def kill_process(args = {}):
return mainClass.instance().kill_process(args)
def kill_process_all(args = {}):
if not 'pid' in args:
return mw.returnData(False, '缺少参数!')
return mainClass.instance().kill_process_all(int(args['pid']))
def set_meter_head(args = {}):
return mainClass.instance().set_meter_head(args)
def remove_service(args = {}):
return mainClass.instance().remove_service(args)
def set_runlevel_state(args = {}):
return mainClass.instance().set_runlevel_state(args)
def get_service_list(args = {}):
return mainClass.instance().get_service_list(args)
def get_run_list(args = {}):
return mainClass.instance().get_run_list(args)
def get_cron_list(args = {}):
return mainClass.instance().get_cron_list(args)
def remove_cron(args = {}):
return mainClass.instance().remove_cron(args)
def pkill_session(args = {}):
return mainClass.instance().pkill_session(args)
def get_who(args = {}):
return mainClass.instance().get_who(args)
def get_process_info(args = {}):
return mainClass.instance().get_process_info(args)
def get_user_list(args = {}):
return mainClass.instance().get_user_list(args)
def remove_user(args = {}):
return mainClass.instance().remove_user(args)
# if __name__ == "__main__":
# print(mc_instance.get_process_list())
# print(mc_instance.get_network_list())
# print(mc_instance.get_process_info({'pid':66647}))
# for x in range(10):
# mc_instance.test_cpu()
# time.sleep(1)
# mc_instance.test_cpu()
# time.sleep(1)
# mc_instance.test_cpu()