|
1 | 1 | #!/usr/bin/env python3
|
2 | 2 | # -*- coding: utf-8 -*-
|
| 3 | +from __future__ import annotations |
| 4 | + |
3 | 5 | import os
|
4 | 6 | import platform
|
5 | 7 | import socket
|
6 | 8 | import sys
|
7 | 9 |
|
8 | 10 | from datetime import datetime, timedelta
|
9 | 11 | from datetime import timezone as tz
|
| 12 | +from typing import Dict, List |
10 | 13 |
|
11 | 14 | import psutil
|
12 | 15 |
|
@@ -61,94 +64,111 @@ def fmt_timedelta(td: timedelta) -> str:
|
61 | 64 | :param td: 时间差对象
|
62 | 65 | :return:
|
63 | 66 | """
|
64 |
| - total_seconds = round(td.total_seconds()) |
65 |
| - return ServerInfo.fmt_seconds(total_seconds) |
| 67 | + return ServerInfo.fmt_seconds(round(td.total_seconds())) |
66 | 68 |
|
67 | 69 | @staticmethod
|
68 | 70 | def get_cpu_info() -> dict[str, float | int]:
|
69 | 71 | """获取 CPU 信息"""
|
70 |
| - cpu_info = {'usage': round(psutil.cpu_percent(percpu=False), 2)} # % |
| 72 | + cpu_info = { |
| 73 | + 'usage': round(psutil.cpu_percent(interval=0.1), 2), # % |
| 74 | + 'logical_num': psutil.cpu_count(logical=True) or 0, |
| 75 | + 'physical_num': psutil.cpu_count(logical=False) or 0, |
| 76 | + 'max_freq': 0.0, |
| 77 | + 'min_freq': 0.0, |
| 78 | + 'current_freq': 0.0, |
| 79 | + } |
71 | 80 |
|
72 | 81 | try:
|
73 |
| - # CPU 频率信息,最大、最小和当前频率 |
74 |
| - cpu_freq = psutil.cpu_freq() |
75 |
| - cpu_info.update({ |
76 |
| - 'max_freq': round(cpu_freq.max, 2), # MHz |
77 |
| - 'min_freq': round(cpu_freq.min, 2), # MHz |
78 |
| - 'current_freq': round(cpu_freq.current, 2), # MHz |
79 |
| - }) |
| 82 | + if hasattr(psutil, 'cpu_freq'): |
| 83 | + cpu_freq = psutil.cpu_freq() |
| 84 | + if cpu_freq: # Some systems return None |
| 85 | + cpu_info.update({ |
| 86 | + 'max_freq': round(cpu_freq.max, 2), |
| 87 | + 'min_freq': round(cpu_freq.min, 2), |
| 88 | + 'current_freq': round(cpu_freq.current, 2), |
| 89 | + }) |
80 | 90 | except Exception:
|
81 |
| - cpu_info.update({'max_freq': 0, 'min_freq': 0, 'current_freq': 0}) |
| 91 | + pass |
82 | 92 |
|
83 |
| - # CPU 逻辑核心数,物理核心数 |
84 |
| - cpu_info.update({ |
85 |
| - 'logical_num': psutil.cpu_count(logical=True), |
86 |
| - 'physical_num': psutil.cpu_count(logical=False), |
87 |
| - }) |
88 | 93 | return cpu_info
|
89 | 94 |
|
90 | 95 | @staticmethod
|
91 | 96 | def get_mem_info() -> dict[str, float]:
|
92 | 97 | """获取内存信息"""
|
93 | 98 | mem = psutil.virtual_memory()
|
| 99 | + gb_factor = 1024**3 |
94 | 100 | return {
|
95 |
| - 'total': round(mem.total / 1024 / 1024 / 1024, 2), # GB |
96 |
| - 'used': round(mem.used / 1024 / 1024 / 1024, 2), # GB |
97 |
| - 'free': round(mem.available / 1024 / 1024 / 1024, 2), # GB |
98 |
| - 'usage': round(mem.percent, 2), # % |
| 101 | + 'total': round(mem.total / gb_factor, 2), |
| 102 | + 'used': round(mem.used / gb_factor, 2), |
| 103 | + 'free': round(mem.available / gb_factor, 2), |
| 104 | + 'usage': round(mem.percent, 2), |
99 | 105 | }
|
100 | 106 |
|
101 | 107 | @staticmethod
|
102 |
| - def get_sys_info() -> dict[str, str]: |
| 108 | + def get_sys_info() -> Dict[str, str]: |
103 | 109 | """获取服务器信息"""
|
| 110 | + hostname = socket.gethostname() |
| 111 | + ip = '127.0.0.1' |
| 112 | + |
104 | 113 | try:
|
105 |
| - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sk: |
106 |
| - sk.connect(('8.8.8.8', 80)) |
107 |
| - ip = sk.getsockname()[0] |
108 |
| - except socket.gaierror: |
109 |
| - ip = '127.0.0.1' |
| 114 | + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: |
| 115 | + s.settimeout(0.5) |
| 116 | + s.connect(('8.8.8.8', 80)) |
| 117 | + ip = s.getsockname()[0] |
| 118 | + except (socket.gaierror, socket.timeout, OSError): |
| 119 | + pass |
110 | 120 |
|
111 | 121 | return {
|
112 |
| - 'name': socket.gethostname(), |
| 122 | + 'name': hostname, |
113 | 123 | 'ip': ip,
|
114 | 124 | 'os': platform.system(),
|
115 | 125 | 'arch': platform.machine(),
|
116 | 126 | }
|
117 | 127 |
|
118 | 128 | @staticmethod
|
119 |
| - def get_disk_info() -> list[dict[str, str]]: |
| 129 | + def get_disk_info() -> List[Dict[str, str]]: |
120 | 130 | """获取磁盘信息"""
|
121 | 131 | disk_info = []
|
122 |
| - for disk in psutil.disk_partitions(): |
123 |
| - usage = psutil.disk_usage(disk.mountpoint) |
124 |
| - disk_info.append({ |
125 |
| - 'dir': disk.mountpoint, |
126 |
| - 'type': disk.fstype, |
127 |
| - 'device': disk.device, |
128 |
| - 'total': ServerInfo.format_bytes(usage.total), |
129 |
| - 'free': ServerInfo.format_bytes(usage.free), |
130 |
| - 'used': ServerInfo.format_bytes(usage.used), |
131 |
| - 'usage': f'{round(usage.percent, 2)} %', |
132 |
| - }) |
| 132 | + for partition in psutil.disk_partitions(all=False): |
| 133 | + try: |
| 134 | + usage = psutil.disk_usage(partition.mountpoint) |
| 135 | + disk_info.append({ |
| 136 | + 'dir': partition.mountpoint, |
| 137 | + 'type': partition.fstype, |
| 138 | + 'device': partition.device, |
| 139 | + 'total': ServerInfo.format_bytes(usage.total), |
| 140 | + 'free': ServerInfo.format_bytes(usage.free), |
| 141 | + 'used': ServerInfo.format_bytes(usage.used), |
| 142 | + 'usage': f'{usage.percent:.2f}%', |
| 143 | + }) |
| 144 | + except (PermissionError, psutil.AccessDenied): |
| 145 | + continue |
133 | 146 | return disk_info
|
134 | 147 |
|
135 | 148 | @staticmethod
|
136 | 149 | def get_service_info() -> dict[str, str | datetime]:
|
137 | 150 | """获取服务信息"""
|
138 | 151 | process = psutil.Process(os.getpid())
|
139 | 152 | mem_info = process.memory_info()
|
140 |
| - start_time = timezone.f_datetime(datetime.utcfromtimestamp(process.create_time()).replace(tzinfo=tz.utc)) |
| 153 | + |
| 154 | + try: |
| 155 | + create_time = datetime.fromtimestamp(process.create_time(), tz=tz.utc) |
| 156 | + start_time = timezone.f_datetime(create_time) |
| 157 | + except (psutil.NoSuchProcess, OSError): |
| 158 | + start_time = timezone.now() |
| 159 | + |
| 160 | + elapsed = ServerInfo.fmt_timedelta(timezone.now() - start_time) |
141 | 161 |
|
142 | 162 | return {
|
143 | 163 | 'name': 'Python3',
|
144 | 164 | 'version': platform.python_version(),
|
145 | 165 | 'home': sys.executable,
|
146 |
| - 'cpu_usage': f'{round(process.cpu_percent(interval=1), 2)} %', |
147 |
| - 'mem_vms': ServerInfo.format_bytes(mem_info.vms), # 虚拟内存, 即当前进程申请的虚拟内存 |
148 |
| - 'mem_rss': ServerInfo.format_bytes(mem_info.rss), # 常驻内存, 即当前进程实际使用的物理内存 |
149 |
| - 'mem_free': ServerInfo.format_bytes(mem_info.vms - mem_info.rss), # 空闲内存 |
| 166 | + 'cpu_usage': f'{process.cpu_percent(interval=0.1):.2f}%', |
| 167 | + 'mem_vms': ServerInfo.format_bytes(mem_info.vms), |
| 168 | + 'mem_rss': ServerInfo.format_bytes(mem_info.rss), |
| 169 | + 'mem_free': ServerInfo.format_bytes(mem_info.vms - mem_info.rss), |
150 | 170 | 'startup': start_time,
|
151 |
| - 'elapsed': ServerInfo.fmt_timedelta(timezone.now() - start_time), |
| 171 | + 'elapsed': elapsed, |
152 | 172 | }
|
153 | 173 |
|
154 | 174 |
|
|
0 commit comments