14 Commits

Author SHA1 Message Date
7ee3eb377e 修复macOS挂载点检查逻辑,确保正确处理系统和应用程序目录
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 21s
Compile / build (x64, ubuntu-latest) (push) Failing after 2m43s
2024-12-10 13:14:10 +08:00
90b4952ea9 修复macOS挂载点检查逻辑,确保正确处理根挂载点
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 17s
Compile / build (x64, ubuntu-latest) (push) Failing after 2m47s
2024-12-10 13:10:44 +08:00
0559212d03 修复macOS分区监控逻辑,确保正确处理挂载点
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 45s
Compile / build (x64, ubuntu-latest) (push) Failing after 2m39s
2024-12-10 13:07:01 +08:00
e74324e21b 修复平台名称大小写问题,确保Linux和macOS的分区监控逻辑正确
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 21s
Compile / build (x64, ubuntu-latest) (push) Failing after 2m54s
2024-12-09 00:30:34 +08:00
48ac46bbb3 增加客户端启动日志并优化线程启动逻辑
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 43s
Compile / build (x64, ubuntu-latest) (push) Failing after 2m8s
2024-12-09 00:26:16 +08:00
b5ba568a66 支持macOS的磁盘分区监控,重构观察逻辑
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 1m0s
Compile / build (x64, ubuntu-latest) (push) Failing after 4m31s
2024-12-08 23:50:45 +08:00
b30b3429ad 新增排序功能
Some checks failed
Compile / build (x64, ubuntu-latest) (push) Failing after 1m27s
Compile / build (x64, windows-latest) (push) Has been cancelled
2024-10-11 01:15:39 +08:00
7cbca85a60 修复部分linux获取发行版错误的问题
Some checks failed
Compile / build (x64, windows-latest) (push) Failing after 10s
Compile / build (x64, ubuntu-latest) (push) Failing after 15s
2024-10-06 04:39:04 +08:00
ce3a07e350 修复部分linux获取发行版错误的问题 2024-10-06 04:36:54 +08:00
9160e7c4b4 修复部分linux获取发行版错误的问题 2024-10-06 04:35:07 +08:00
8e2c5c24b8 安装脚本添加本地化 2024-10-06 04:32:12 +08:00
c63d84106b 安装脚本添加本地化 2024-10-06 02:17:41 +08:00
0d7b7700de 修复脚本执行错误 2024-10-05 23:13:33 +08:00
b5bf2c1de6 修复脚本执行错误 2024-10-05 23:08:40 +08:00
5 changed files with 135 additions and 74 deletions

View File

@@ -57,8 +57,8 @@ _✨ 服务器状态 - 客户端 ✨_
### 命令
- `server-status <server> <token> <id> run` - 运行客户端
- `server-status <server> <token> <id> rm` - 从服务端移除主机
- `python main.py <server> <token> <id> run` - 运行客户端
- `python.main.py <server> <token> <id> rm` - 从服务端移除主机
#### 可选项
@@ -71,7 +71,7 @@ _✨ 服务器状态 - 客户端 ✨_
#### 示例
```shell
server_status https://status.liteyuki.icu 114514 myhost run -n "MyHost" --labels "标签1,标签2" --interval 5 --location "Chongqing" --link "https://example.com"
python main.py https://status.liteyuki.icu 114514 myhost run -n "MyHost" --labels "标签1,标签2" --interval 5 --location "Chongqing" --link "https://example.com"
```
## 📝 其他

View File

@@ -10,40 +10,36 @@ fi
# check install dir
install_dir="/opt"
echo -n "Install directory? (default: $install_dir/server-status-client): " && read -r install_dir_input
echo -n "安装目录? (默认: $install_dir/server-status-client): " && read -r install_dir_input
if [ -n "$install_dir_input" ]; then
install_dir="$install_dir_input"
fi
# check server
echo -n "Server? (required): " && read -r server
echo -n "服务端地址? (必须): " && read -r server
if [ -z "$server" ]; then
echo "Server is required"
echo "服务端地址是必须的"
exit 1
fi
# check token
echo -n "Token? (required): " && read -r token
if [ -z "$token" ]; then
echo "Token is required"
exit 1
fi
echo -n "令牌? (必须或留空): " && read -r token
# check hostname
hostname=$(hostname)
echo -n "Hostname? (default: $hostname): " && read -r hostname_input
echo -n "此主机名? (默认: $hostname): " && read -r hostname_input
if [ -n "$hostname_input" ]; then
hostname="$hostname_input"
fi
# labels
echo -n "Labels? (space separated): " && read -r labels_input
echo -n "标签们? (空格分隔): " && read -r labels_input
if [ -n "$labels_input" ]; then
labels="$labels_input"
fi
# location
echo -n "Location? (optional): " && read -r location_input
echo -n "地理位置? (可选|自定义): " && read -r location_input
if [ -n "$location_input" ]; then
location="$location_input"
fi
@@ -52,7 +48,7 @@ fi
repo2="https://git.liteyuki.icu/snowykami/server-status-client"
# try 1 if failed try 2
git clone "$repo2" "$install_dir/server-status-client"
cd "$install_dir/server-status-client" || { echo "Failed to clone repo"; exit 1; }
cd "$install_dir/server-status-client" || { echo "克隆失败"; exit 1; }
# create venv
python3 -m venv venv
@@ -60,22 +56,22 @@ python_exe="./venv/bin/python"
# check if venv is created
if [ ! -f "$python_exe" ]; then
echo "Failed to create venv"
echo "创建虚拟环境失败"
exit 1
fi
echo "venv created successfully"
echo "虚拟环境创建成功"
# install the required packages
echo "Installing the required packages"
echo "正在安装依赖包..."
$python_exe -m pip install pdm -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
$python_exe -m pdm install
# create the systemd service
echo "Creating the systemd service"
echo "正在创建服务..."
# generate random id
# shellcheck disable=SC2002
id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
bash -c "cat <<EOF > /etc/systemd/system/server-status-client.service
[Unit]
@@ -97,4 +93,4 @@ EOF"
systemctl enable server-status-client
systemctl start server-status-client
echo "server-status-client installed successfully"
echo "安装完成,服务已启动"

View File

@@ -74,7 +74,7 @@ echo "Creating the systemd service"
# generate random id
# shellcheck disable=SC2002
id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
bash -c "cat <<EOF > /etc/systemd/system/server-status-client.service
[Unit]

View File

@@ -8,7 +8,41 @@ import requests
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",
"/System",
"/Applications",
"/private",
"/Library",
)
include_partition_prefix_mac = ("/Volumes")
os_name = "" # linux下为发行版名称windows下为Windows macOS下为Darwin
os_version = "" # linux下为发行版版本windows下为Windows版本
try:
# read /etc/os-release
with open("/etc/os-release") as f:
os_release = f.read()
# 找到NAME=和VERSION=的行
for line in os_release.split("\n"):
if line.startswith("NAME="):
os_name = line.split("=")[1].replace('"', "")
elif line.startswith("VERSION_ID="):
os_version = line.split("=")[1].replace('"', "")
except FileNotFoundError:
os_name = platform.system()
os_version = platform.release()
print("Current OS:", os_name, os_version)
def log(*args):
@@ -29,6 +63,7 @@ def get_network_speed(interval) -> tuple[int, int]:
class Hardware:
os_release: str = ""
mem_total: int = psutil.virtual_memory().total
mem_used: int = psutil.virtual_memory().used
@@ -112,7 +147,9 @@ class Api:
"""
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):
obj = obj.format(**self.variables)
elif isinstance(obj, dict):
@@ -125,8 +162,17 @@ class Api:
class Client:
def __init__(self, addr: str, token: str, client_id: str, name: str = "", location: str = "", labels: list[str] = [], link: str = "",
interval: int = 2):
def __init__(
self,
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 = self.api.group("/client")
self.api.add_headers(Authorization="{token}")
@@ -140,15 +186,66 @@ class Client:
self.link = link
self.interval = interval
self.start_time = psutil.boot_time()
self.start_time: float = psutil.boot_time()
self.hardware = Hardware()
log("Client initialized",
f"Name: {self.name}({self.client_id}), Location: {self.location}, Labels: {self.labels}")
log(
"Client initialized",
f"Name: {self.name}({self.client_id}), Location: {self.location}, Labels: {self.labels}",
)
def start(self):
self.observe()
log("Starting client")
threading.Thread(target=self._start_obs, daemon=True).start()
threading.Thread(target=self._start_post, daemon=True).start()
while True:
time.sleep(1)
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() in ("Linux", "Darwin")
and (
part.mountpoint.startswith(
excluded_partition_prefix
)
)
)
):
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:
try:
resp = self.get_ping()
@@ -156,9 +253,13 @@ class Client:
log(f"Connected to server {self.addr}")
break
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:
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)
while True:
@@ -185,10 +286,11 @@ class Client:
"id": self.client_id,
"name": self.name,
"os": {
"name": platform.system(),
"version": platform.version(),
"machine": platform.machine(),
"release": platform.release(),
"name": platform.system(), # 系统类型 linux|windows|darwin
"version": os_name + os_version,
# 系统版本复杂描述 #1 SMP PREEMPT_DYNAMIC Fri Sep 13 10:42:50 UTC 2024 (5c05eeb)
"machine": platform.machine(), # 机器类型 x86_64
"release": os_version, # 系统版本
},
"labels": self.labels,
"location": self.location,
@@ -221,42 +323,5 @@ class Client:
},
}
def observe(self):
"""
观察硬件状态并更新
Returns:
"""
def _observe():
while True:
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")
threading.Thread(target=_observe, daemon=True).start()
def remove(self, client_id) -> requests.Response:
return self.api.delete("/host", data={"id": client_id})

View File

@@ -3,7 +3,7 @@ import socket
from arclet.alconna import Alconna, Subcommand, Option, Args, MultiVar
server_status_alc = Alconna(
server_status_alc = Alconna( # type: ignore
"server_status",
Args["server", str]["token", str]["id", str],
Subcommand(