支持macOS的磁盘分区监控,重构观察逻辑
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 1m0s
Compile / build (x64, ubuntu-latest) (push) Failing after 4m31s

This commit is contained in:
远野千束(神羽) 2024-12-08 23:50:45 +08:00
parent b30b3429ad
commit b5ba568a66

View File

@ -8,9 +8,20 @@ import requests
from server_status.timezone import get_timezone from server_status.timezone import get_timezone
excluded_partition_prefix = ("/var", "/boot", "/run", "/proc", "/sys", "/dev", "/tmp", "/snap") excluded_partition_prefix = (
"/var",
"/boot",
"/run",
"/proc",
"/sys",
"/dev",
"/tmp",
"/snap",
)
os_name = "" # linux下为发行版名称windows下为Windows include_partition_prefix_mac = ("/Volumes",)
os_name = "" # linux下为发行版名称windows下为Windows macOS下为Darwin
os_version = "" # linux下为发行版版本windows下为Windows版本 os_version = "" # linux下为发行版版本windows下为Windows版本
try: try:
# read /etc/os-release # read /etc/os-release
@ -19,9 +30,9 @@ try:
# 找到NAME=和VERSION=的行 # 找到NAME=和VERSION=的行
for line in os_release.split("\n"): for line in os_release.split("\n"):
if line.startswith("NAME="): if line.startswith("NAME="):
os_name = line.split("=")[1].replace('"', '') os_name = line.split("=")[1].replace('"', "")
elif line.startswith("VERSION_ID="): elif line.startswith("VERSION_ID="):
os_version = line.split("=")[1].replace('"', '') os_version = line.split("=")[1].replace('"', "")
except FileNotFoundError: except FileNotFoundError:
os_name = platform.system() os_name = platform.system()
os_version = platform.release() os_version = platform.release()
@ -131,7 +142,9 @@ class Api:
""" """
self.headers.update(self.format(headers)) self.headers.update(self.format(headers))
def format(self, obj: str | list[str] | dict[str, Any]) -> str | list[str] | dict[str, Any]: def format(
self, obj: str | list[str] | dict[str, Any]
) -> str | list[str] | dict[str, Any]:
if isinstance(obj, str): if isinstance(obj, str):
obj = obj.format(**self.variables) obj = obj.format(**self.variables)
elif isinstance(obj, dict): elif isinstance(obj, dict):
@ -144,9 +157,17 @@ class Api:
class Client: class Client:
def __init__(self, addr: str, token: str, client_id: str, name: str = "", location: str = "", def __init__(
labels: list[str] = [], link: str = "", self,
interval: int = 2): addr: str,
token: str,
client_id: str,
name: str = "",
location: str = "",
labels: list[str] = [],
link: str = "",
interval: int = 2,
):
self.api = Api(addr, {"token": token, "id": client_id}) self.api = Api(addr, {"token": token, "id": client_id})
self.api = self.api.group("/client") self.api = self.api.group("/client")
self.api.add_headers(Authorization="{token}") self.api.add_headers(Authorization="{token}")
@ -160,14 +181,69 @@ class Client:
self.link = link self.link = link
self.interval = interval self.interval = interval
self.start_time = psutil.boot_time() self.start_time: float = psutil.boot_time()
self.hardware = Hardware() self.hardware = Hardware()
log("Client initialized", log(
f"Name: {self.name}({self.client_id}), Location: {self.location}, Labels: {self.labels}") "Client initialized",
f"Name: {self.name}({self.client_id}), Location: {self.location}, Labels: {self.labels}",
)
def start(self): def start(self):
self.observe() threading.Thread(target=self._start_obs, daemon=True).start()
threading.Thread(target=self._start_post, daemon=True).start()
def _start_obs(self):
"""启动监控记录线程"""
while True:
try:
self.hardware.mem_total = psutil.virtual_memory().total
self.hardware.mem_used = psutil.virtual_memory().used
self.hardware.swap_total = psutil.swap_memory().total
self.hardware.swap_used = psutil.swap_memory().used
self.hardware.cpu_cores = psutil.cpu_count(logical=False)
self.hardware.cpu_logics = psutil.cpu_count(logical=True)
for part in psutil.disk_partitions():
try:
usage = psutil.disk_usage(part.mountpoint)
if (
(
platform.system() == "linux"
and (
part.mountpoint.startswith(
excluded_partition_prefix
)
)
)
or (
platform.system() == "darwin"
and not part.mountpoint.startswith(
include_partition_prefix_mac
)
)
or usage.total == 0
):
continue
self.hardware.disks[part.device] = {
"mountpoint": part.mountpoint,
"device": part.device,
"fstype": part.fstype,
"total": usage.total,
"used": usage.used,
}
except:
pass
self.hardware.cpu_percent = psutil.cpu_percent(1)
self.hardware.net_up, self.hardware.net_down = get_network_speed(1)
log("Observed")
except Exception as e:
log(f"Failed to observe: {e}")
def _start_post(self):
"""启动上报进程"""
while True: while True:
try: try:
resp = self.get_ping() resp = self.get_ping()
@ -175,9 +251,13 @@ class Client:
log(f"Connected to server {self.addr}") log(f"Connected to server {self.addr}")
break break
else: else:
log(f"Failed to connect to server {self.addr}, retrying in 5 seconds: {resp.text}") log(
f"Failed to connect to server {self.addr}, retrying in 5 seconds: {resp.text}"
)
except Exception as e: except Exception as e:
log(f"Failed to connect to server {self.addr}, retrying in 5 seconds: {e}") log(
f"Failed to connect to server {self.addr}, retrying in 5 seconds: {e}"
)
time.sleep(5) time.sleep(5)
while True: while True:
@ -241,45 +321,5 @@ class Client:
}, },
} }
def observe(self):
"""
观察硬件状态并更新
Returns:
"""
def _observe():
while True:
try:
self.hardware.mem_total = psutil.virtual_memory().total
self.hardware.mem_used = psutil.virtual_memory().used
self.hardware.swap_total = psutil.swap_memory().total
self.hardware.swap_used = psutil.swap_memory().used
self.hardware.cpu_cores = psutil.cpu_count(logical=False)
self.hardware.cpu_logics = psutil.cpu_count(logical=True)
for part in psutil.disk_partitions():
try:
usage = psutil.disk_usage(part.mountpoint)
if part.mountpoint.startswith(excluded_partition_prefix) or usage.total == 0:
continue
self.hardware.disks[part.device] = {
"mountpoint": part.mountpoint,
"device": part.device,
"fstype": part.fstype,
"total": usage.total,
"used": usage.used,
}
except:
pass
self.hardware.cpu_percent = psutil.cpu_percent(1)
self.hardware.net_up, self.hardware.net_down = get_network_speed(1)
log("Observed")
except Exception as e:
log(f"Failed to observe: {e}")
threading.Thread(target=_observe).start()
def remove(self, client_id) -> requests.Response: def remove(self, client_id) -> requests.Response:
return self.api.delete("/host", data={"id": client_id}) return self.api.delete("/host", data={"id": client_id})