2025-09-13 08:23:54 +08:00
|
|
|
|
import shutil, subprocess, time, threading, psutil
|
|
|
|
|
|
from flask import current_app
|
|
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
class SystemStatus:
|
2025-01-24 19:19:17 +08:00
|
|
|
|
def __init__(self):
|
|
|
|
|
|
self.CPU = CPU()
|
|
|
|
|
|
self.MemoryVirtual = Memory('virtual')
|
|
|
|
|
|
self.MemorySwap = Memory('swap')
|
|
|
|
|
|
self.Disks = Disks()
|
|
|
|
|
|
self.NetworkInterfaces = NetworkInterfaces()
|
|
|
|
|
|
self.Processes = Processes()
|
|
|
|
|
|
def toJson(self):
|
2025-08-27 11:42:06 +08:00
|
|
|
|
process = [
|
|
|
|
|
|
threading.Thread(target=self.CPU.getCPUPercent),
|
|
|
|
|
|
threading.Thread(target=self.CPU.getPerCPUPercent),
|
|
|
|
|
|
threading.Thread(target=self.NetworkInterfaces.getData)
|
|
|
|
|
|
]
|
|
|
|
|
|
for p in process:
|
|
|
|
|
|
p.start()
|
|
|
|
|
|
for p in process:
|
|
|
|
|
|
p.join()
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-24 19:19:17 +08:00
|
|
|
|
return {
|
|
|
|
|
|
"CPU": self.CPU,
|
|
|
|
|
|
"Memory": {
|
|
|
|
|
|
"VirtualMemory": self.MemoryVirtual,
|
|
|
|
|
|
"SwapMemory": self.MemorySwap
|
|
|
|
|
|
},
|
|
|
|
|
|
"Disks": self.Disks,
|
|
|
|
|
|
"NetworkInterfaces": self.NetworkInterfaces,
|
2025-08-27 17:48:28 +08:00
|
|
|
|
"NetworkInterfacesPriority": self.NetworkInterfaces.getInterfacePriorities(),
|
2025-01-24 19:19:17 +08:00
|
|
|
|
"Processes": self.Processes
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
|
|
|
|
|
|
class CPU:
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
self.cpu_percent: float = 0
|
|
|
|
|
|
self.cpu_percent_per_cpu: list[float] = []
|
2025-09-13 08:23:54 +08:00
|
|
|
|
|
2025-08-27 11:42:06 +08:00
|
|
|
|
def getCPUPercent(self):
|
|
|
|
|
|
try:
|
|
|
|
|
|
self.cpu_percent = psutil.cpu_percent(interval=1)
|
|
|
|
|
|
except Exception as e:
|
2025-09-13 08:23:54 +08:00
|
|
|
|
current_app.logger.error("Get CPU Percent error", e)
|
2025-08-27 11:42:06 +08:00
|
|
|
|
|
|
|
|
|
|
def getPerCPUPercent(self):
|
2025-01-24 00:01:29 +08:00
|
|
|
|
try:
|
2025-08-27 11:42:06 +08:00
|
|
|
|
self.cpu_percent_per_cpu = psutil.cpu_percent(interval=1, percpu=True)
|
2025-01-24 00:01:29 +08:00
|
|
|
|
except Exception as e:
|
2025-09-13 08:23:54 +08:00
|
|
|
|
current_app.logger.error("Get Per CPU Percent error", e)
|
2025-08-27 11:42:06 +08:00
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
def toJson(self):
|
|
|
|
|
|
return self.__dict__
|
|
|
|
|
|
|
|
|
|
|
|
class Memory:
|
|
|
|
|
|
def __init__(self, memoryType: str):
|
2025-01-24 19:19:17 +08:00
|
|
|
|
self.__memoryType__ = memoryType
|
2025-01-24 00:01:29 +08:00
|
|
|
|
self.total = 0
|
|
|
|
|
|
self.available = 0
|
|
|
|
|
|
self.percent = 0
|
|
|
|
|
|
def getData(self):
|
2025-01-24 19:19:17 +08:00
|
|
|
|
try:
|
|
|
|
|
|
if self.__memoryType__ == "virtual":
|
|
|
|
|
|
memory = psutil.virtual_memory()
|
2025-09-13 19:05:32 +08:00
|
|
|
|
self.available = memory.available
|
2025-01-24 19:19:17 +08:00
|
|
|
|
else:
|
|
|
|
|
|
memory = psutil.swap_memory()
|
2025-09-13 19:05:32 +08:00
|
|
|
|
self.available = memory.free
|
2025-01-24 19:19:17 +08:00
|
|
|
|
self.total = memory.total
|
2025-09-13 19:05:32 +08:00
|
|
|
|
|
2025-01-24 19:19:17 +08:00
|
|
|
|
self.percent = memory.percent
|
|
|
|
|
|
except Exception as e:
|
2025-09-13 08:23:54 +08:00
|
|
|
|
current_app.logger.error("Get Memory percent error", e)
|
2025-01-24 00:01:29 +08:00
|
|
|
|
def toJson(self):
|
|
|
|
|
|
self.getData()
|
|
|
|
|
|
return self.__dict__
|
2025-01-24 19:19:17 +08:00
|
|
|
|
|
|
|
|
|
|
class Disks:
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
self.disks : list[Disk] = []
|
|
|
|
|
|
def getData(self):
|
|
|
|
|
|
try:
|
|
|
|
|
|
self.disks = list(map(lambda x : Disk(x.mountpoint), psutil.disk_partitions()))
|
|
|
|
|
|
except Exception as e:
|
2025-09-13 08:23:54 +08:00
|
|
|
|
current_app.logger.error("Get Disk percent error", e)
|
2025-01-24 19:19:17 +08:00
|
|
|
|
def toJson(self):
|
|
|
|
|
|
self.getData()
|
|
|
|
|
|
return self.disks
|
|
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
class Disk:
|
|
|
|
|
|
def __init__(self, mountPoint: str):
|
|
|
|
|
|
self.total = 0
|
|
|
|
|
|
self.used = 0
|
|
|
|
|
|
self.free = 0
|
|
|
|
|
|
self.percent = 0
|
|
|
|
|
|
self.mountPoint = mountPoint
|
|
|
|
|
|
def getData(self):
|
2025-01-24 19:19:17 +08:00
|
|
|
|
try:
|
|
|
|
|
|
disk = psutil.disk_usage(self.mountPoint)
|
|
|
|
|
|
self.total = disk.total
|
|
|
|
|
|
self.free = disk.free
|
|
|
|
|
|
self.used = disk.used
|
|
|
|
|
|
self.percent = disk.percent
|
|
|
|
|
|
except Exception as e:
|
2025-09-13 08:23:54 +08:00
|
|
|
|
current_app.logger.error("Get Disk percent error", e)
|
2025-01-24 00:01:29 +08:00
|
|
|
|
def toJson(self):
|
|
|
|
|
|
self.getData()
|
|
|
|
|
|
return self.__dict__
|
|
|
|
|
|
|
|
|
|
|
|
class NetworkInterfaces:
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
self.interfaces = {}
|
2025-08-27 17:48:28 +08:00
|
|
|
|
|
|
|
|
|
|
def getInterfacePriorities(self):
|
|
|
|
|
|
if shutil.which("ip"):
|
|
|
|
|
|
result = subprocess.check_output(["ip", "route", "show"]).decode()
|
|
|
|
|
|
priorities = {}
|
|
|
|
|
|
for line in result.splitlines():
|
|
|
|
|
|
if "metric" in line and "dev" in line:
|
|
|
|
|
|
parts = line.split()
|
|
|
|
|
|
dev = parts[parts.index("dev")+1]
|
|
|
|
|
|
metric = int(parts[parts.index("metric")+1])
|
|
|
|
|
|
if dev not in priorities:
|
|
|
|
|
|
priorities[dev] = metric
|
|
|
|
|
|
return priorities
|
|
|
|
|
|
return {}
|
|
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
def getData(self):
|
2025-08-27 17:48:28 +08:00
|
|
|
|
self.interfaces.clear()
|
2025-01-24 19:19:17 +08:00
|
|
|
|
try:
|
|
|
|
|
|
network = psutil.net_io_counters(pernic=True, nowrap=True)
|
|
|
|
|
|
for i in network.keys():
|
|
|
|
|
|
self.interfaces[i] = network[i]._asdict()
|
2025-08-27 11:42:06 +08:00
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
network = psutil.net_io_counters(pernic=True, nowrap=True)
|
|
|
|
|
|
for i in network.keys():
|
|
|
|
|
|
self.interfaces[i]['realtime'] = {
|
|
|
|
|
|
'sent': round((network[i].bytes_sent - self.interfaces[i]['bytes_sent']) / 1024 / 1024, 4),
|
|
|
|
|
|
'recv': round((network[i].bytes_recv - self.interfaces[i]['bytes_recv']) / 1024 / 1024, 4)
|
|
|
|
|
|
}
|
2025-01-24 19:19:17 +08:00
|
|
|
|
except Exception as e:
|
2025-09-13 08:23:54 +08:00
|
|
|
|
current_app.logger.error("Get network error", e)
|
|
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
def toJson(self):
|
|
|
|
|
|
return self.interfaces
|
|
|
|
|
|
|
2025-04-20 02:52:22 +08:00
|
|
|
|
class Process:
|
|
|
|
|
|
def __init__(self, name, command, pid, percent):
|
|
|
|
|
|
self.name = name
|
|
|
|
|
|
self.command = command
|
|
|
|
|
|
self.pid = pid
|
|
|
|
|
|
self.percent = percent
|
|
|
|
|
|
def toJson(self):
|
|
|
|
|
|
return self.__dict__
|
|
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
class Processes:
|
|
|
|
|
|
def __init__(self):
|
2025-04-21 17:25:12 +08:00
|
|
|
|
self.CPU_Top_10_Processes: list[Process] = []
|
|
|
|
|
|
self.Memory_Top_10_Processes: list[Process] = []
|
2025-01-24 00:01:29 +08:00
|
|
|
|
def getData(self):
|
2025-10-14 08:48:33 +02:00
|
|
|
|
try:
|
|
|
|
|
|
processes = list(psutil.process_iter())
|
|
|
|
|
|
|
|
|
|
|
|
cpu_processes = []
|
|
|
|
|
|
memory_processes = []
|
|
|
|
|
|
|
|
|
|
|
|
for proc in processes:
|
|
|
|
|
|
try:
|
|
|
|
|
|
name = proc.name()
|
|
|
|
|
|
cmdline = " ".join(proc.cmdline())
|
|
|
|
|
|
pid = proc.pid
|
|
|
|
|
|
cpu_percent = proc.cpu_percent()
|
|
|
|
|
|
mem_percent = proc.memory_percent()
|
|
|
|
|
|
|
|
|
|
|
|
# Create Process object for CPU and memory tracking
|
|
|
|
|
|
cpu_process = Process(name, cmdline, pid, cpu_percent)
|
|
|
|
|
|
mem_process = Process(name, cmdline, pid, mem_percent)
|
|
|
|
|
|
|
|
|
|
|
|
cpu_processes.append(cpu_process)
|
|
|
|
|
|
memory_processes.append(mem_process)
|
|
|
|
|
|
|
|
|
|
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
|
|
|
|
# Skip processes we can’t access or that no longer exist
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
# Sort by CPU and memory usage (descending order)
|
|
|
|
|
|
cpu_sorted = sorted(cpu_processes, key=lambda p: p.percent, reverse=True)
|
|
|
|
|
|
mem_sorted = sorted(memory_processes, key=lambda p: p.percent, reverse=True)
|
|
|
|
|
|
|
|
|
|
|
|
# Get top 20 processes for each
|
|
|
|
|
|
self.CPU_Top_10_Processes = cpu_sorted[:20]
|
|
|
|
|
|
self.Memory_Top_10_Processes = mem_sorted[:20]
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
current_app.logger.error("Get processes error", e)
|
2025-09-13 08:23:54 +08:00
|
|
|
|
|
2025-01-24 00:01:29 +08:00
|
|
|
|
def toJson(self):
|
|
|
|
|
|
self.getData()
|
|
|
|
|
|
return {
|
|
|
|
|
|
"cpu_top_10": self.CPU_Top_10_Processes,
|
|
|
|
|
|
"memory_top_10": self.Memory_Top_10_Processes
|
2025-01-24 19:19:17 +08:00
|
|
|
|
}
|