mirror of
https://github.com/snowykami/server-status-client.git
synced 2025-06-06 12:45:21 +00:00
Compare commits
75 Commits
Author | SHA1 | Date | |
---|---|---|---|
7ee3eb377e | |||
90b4952ea9 | |||
0559212d03 | |||
e74324e21b | |||
48ac46bbb3 | |||
b5ba568a66 | |||
b30b3429ad | |||
7cbca85a60 | |||
ce3a07e350 | |||
9160e7c4b4 | |||
8e2c5c24b8 | |||
c63d84106b | |||
0d7b7700de | |||
b5bf2c1de6 | |||
87418edeea | |||
5c089873ca | |||
79242f9dd6 | |||
22feee38ee | |||
e0aa6adbeb | |||
87859a58f8 | |||
d1098cf735 | |||
62096e5f4d | |||
26db6fe7d0 | |||
3b09c0650d | |||
fb7e3144d3 | |||
c271378c71 | |||
5834abcd33 | |||
67475ef499 | |||
42c4db6c01 | |||
4af3579d70 | |||
cd56065e32 | |||
3c960896f4 | |||
c2a3966f37 | |||
3fa94f653d | |||
4cb1fcdb21 | |||
657cd1a80f | |||
3d14b5a18e | |||
2c3cda6e46 | |||
e03c99a9f6 | |||
db7aeabe7b | |||
89d7fa3145 | |||
833c96cbc5 | |||
2e4fd493c5 | |||
0360e58cc1 | |||
7c74a40d45 | |||
5c649089ff | |||
331297691a | |||
eb6a57d5a7 | |||
b6f6eba1cf | |||
aca1074b12 | |||
a859a975a2 | |||
993cd3409a | |||
d86141e83d | |||
2dc156288b | |||
cd8fd6bb87 | |||
1935faa1f2 | |||
c97544cda3 | |||
b57bb4ec10 | |||
afbedc665c | |||
575203aedc | |||
dd596f0a93 | |||
42d5795335 | |||
4064f904d0 | |||
521af9695c | |||
62903a6680 | |||
5f33564d3f | |||
02af22862d | |||
9ccb98b1f8 | |||
55ba28d98d | |||
0b60781f3a | |||
803f742d85 | |||
2e0c8ff194 | |||
af970a77ed | |||
a579c76002 | |||
66d0782106 |
52
.github/workflows/nuitka-compile.yml
vendored
Normal file
52
.github/workflows/nuitka-compile.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
name: Compile
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
|
arch: [ x64]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check-out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
architecture: ${{ matrix.arch }}
|
||||||
|
cache: 'pip'
|
||||||
|
cache-dependency-path: |
|
||||||
|
**/requirements*.txt
|
||||||
|
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
pip install pdm
|
||||||
|
pdm install --no-lock
|
||||||
|
|
||||||
|
- name: Build Executable
|
||||||
|
uses: Nuitka/Nuitka-Action@main
|
||||||
|
with:
|
||||||
|
nuitka-version: main
|
||||||
|
script-name: main.py
|
||||||
|
onefile: true
|
||||||
|
standalone: true
|
||||||
|
follow-imports: true
|
||||||
|
|
||||||
|
- name: Upload Artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{ runner.os }} Build
|
||||||
|
path: |
|
||||||
|
build/*.exe
|
||||||
|
build/*.bin
|
||||||
|
build/*.app/**/*
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -121,6 +121,10 @@ celerybeat.pid
|
|||||||
# SageMath parsed files
|
# SageMath parsed files
|
||||||
*.sage.py
|
*.sage.py
|
||||||
|
|
||||||
|
pdm.lock
|
||||||
|
start.cmd
|
||||||
|
start.sh
|
||||||
|
|
||||||
# Environments
|
# Environments
|
||||||
.env
|
.env
|
||||||
.venv
|
.venv
|
||||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Snowykami
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
70
README.md
70
README.md
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
# server-status-client
|
# server-status-client
|
||||||
@ -20,30 +19,49 @@ _✨ 服务器状态 - 客户端 ✨_
|
|||||||
|
|
||||||
服务器状态的客户端命令行工具
|
服务器状态的客户端命令行工具
|
||||||
|
|
||||||
|
- 跨平台支持
|
||||||
|
- 自动上报服务器状态
|
||||||
|
- 支持自定义标签、地域、链接等信息
|
||||||
|
|
||||||
## 💿 安装
|
## 💿 安装
|
||||||
|
- 先决条件:`curl` `python3` `pip` `venv` `git`
|
||||||
|
|
||||||
<details open>
|
- Linux 可使用脚本安装,带自动部署和自启动
|
||||||
<summary>使用 pip 安装(确保包路径在环境变量下)</summary>
|
|
||||||
|
|
||||||
pip install server-status
|
```shell
|
||||||
|
sudo bash -c "$(curl -sSL https://raw.githubusercontent.com/snowykami/server-status-client/refs/heads/main/deploy.sh)"
|
||||||
|
```
|
||||||
|
如果位于中国大陆无法访问GitHub,可使用中国版脚本
|
||||||
|
```shell
|
||||||
|
sudo bash -c "$(curl -sSL https://git.liteyuki.icu/snowykami/server-status-client/raw/branch/main/deploy-cn.sh)"
|
||||||
|
```
|
||||||
|
|
||||||
</details>
|
- 或手动部署
|
||||||
|
|
||||||
Debian系请使用pipx安装
|
```shell
|
||||||
|
# 克隆仓库
|
||||||
|
git clone https://github.com/snowykami/server-status-client
|
||||||
|
cd server-status-client
|
||||||
|
|
||||||
```bash
|
# 配置环境
|
||||||
sudo apt install pipx
|
python3 -m venv venv
|
||||||
pipx install server-status
|
source venv/bin/activate
|
||||||
|
# 安装依赖
|
||||||
|
pip install pdm
|
||||||
|
pdm install
|
||||||
|
|
||||||
|
# 如需自启动请自行添加到系统服务
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🎉 使用
|
## 🎉 使用
|
||||||
|
|
||||||
### 命令
|
### 命令
|
||||||
|
|
||||||
- `server_status <server> <token> <id> run` - 运行客户端
|
- `python main.py <server> <token> <id> run` - 运行客户端
|
||||||
- `server_status <server> <token> <id> rm` - 从服务端移除主机
|
- `python.main.py <server> <token> <id> rm` - 从服务端移除主机
|
||||||
|
|
||||||
#### 可选项
|
#### 可选项
|
||||||
|
|
||||||
- `-n|--name` - 设置主机名称
|
- `-n|--name` - 设置主机名称
|
||||||
- `--labels` - 设置主机标签
|
- `--labels` - 设置主机标签
|
||||||
- `--interval` - 设置上报间隔
|
- `--interval` - 设置上报间隔
|
||||||
@ -51,34 +69,22 @@ pipx install server-status
|
|||||||
- `--link` - 设置前端点击跳转链接
|
- `--link` - 设置前端点击跳转链接
|
||||||
|
|
||||||
#### 示例
|
#### 示例
|
||||||
|
|
||||||
```shell
|
```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"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📝 其他
|
## 📝 其他
|
||||||
|
|
||||||
### 开机启动
|
### 开机启动
|
||||||
执行以下命令
|
|
||||||
|
- 安装脚本已自动添加到系统服务
|
||||||
|
|
||||||
|
### 更新
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo touch /etc/systemd/system/server-status-client.service
|
git pull
|
||||||
|
sudo systemctl restart server-status-client
|
||||||
sudo bash -c 'cat <<EOF > /etc/systemd/system/server-status-client.service
|
|
||||||
[Unit]
|
|
||||||
Description=Server Status Client
|
|
||||||
After=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=sudo server_status <server> <token> <id> run # 请替换为实际参数
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=10
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF'
|
|
||||||
|
|
||||||
sudo systemctl enable server-status-client
|
|
||||||
sudo systemctl start server-status-client
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 服务端
|
### 服务端
|
||||||
|
96
deploy-cn.sh
Executable file
96
deploy-cn.sh
Executable file
@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 部署脚本中国大陆可用版本
|
||||||
|
|
||||||
|
# check if sudo is used
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Please run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check install dir
|
||||||
|
install_dir="/opt"
|
||||||
|
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 "服务端地址? (必须): " && read -r server
|
||||||
|
if [ -z "$server" ]; then
|
||||||
|
echo "服务端地址是必须的"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check token
|
||||||
|
echo -n "令牌? (必须或留空): " && read -r token
|
||||||
|
|
||||||
|
# check hostname
|
||||||
|
hostname=$(hostname)
|
||||||
|
echo -n "此主机名? (默认: $hostname): " && read -r hostname_input
|
||||||
|
if [ -n "$hostname_input" ]; then
|
||||||
|
hostname="$hostname_input"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# labels
|
||||||
|
echo -n "标签们? (空格分隔): " && read -r labels_input
|
||||||
|
if [ -n "$labels_input" ]; then
|
||||||
|
labels="$labels_input"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# location
|
||||||
|
echo -n "地理位置? (可选|自定义): " && read -r location_input
|
||||||
|
if [ -n "$location_input" ]; then
|
||||||
|
location="$location_input"
|
||||||
|
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 "克隆失败"; exit 1; }
|
||||||
|
|
||||||
|
# create venv
|
||||||
|
python3 -m venv venv
|
||||||
|
python_exe="./venv/bin/python"
|
||||||
|
|
||||||
|
# check if venv is created
|
||||||
|
if [ ! -f "$python_exe" ]; then
|
||||||
|
echo "创建虚拟环境失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "虚拟环境创建成功"
|
||||||
|
|
||||||
|
# install 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 "正在创建服务..."
|
||||||
|
|
||||||
|
# generate random id
|
||||||
|
# shellcheck disable=SC2002
|
||||||
|
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]
|
||||||
|
Description=Server Status Client
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=$install_dir/server-status-client/venv/bin/python main.py $server $token $id run -n $hostname --labels $labels --location $location
|
||||||
|
WorkingDirectory=$install_dir/server-status-client
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF"
|
||||||
|
|
||||||
|
# enable and start the service
|
||||||
|
systemctl enable server-status-client
|
||||||
|
systemctl start server-status-client
|
||||||
|
|
||||||
|
echo "安装完成,服务已启动"
|
0
deploy.cmd
Normal file
0
deploy.cmd
Normal file
99
deploy.sh
Executable file
99
deploy.sh
Executable file
@ -0,0 +1,99 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# check if sudo is used
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Please run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check install dir
|
||||||
|
install_dir="/opt"
|
||||||
|
echo -n "Install directory? (default: $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
|
||||||
|
if [ -z "$server" ]; then
|
||||||
|
echo "Server is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check token
|
||||||
|
echo -n "Token? (required): " && read -r token
|
||||||
|
if [ -z "$token" ]; then
|
||||||
|
echo "Token is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check hostname
|
||||||
|
hostname=$(hostname)
|
||||||
|
echo -n "Hostname? (default: $hostname): " && read -r hostname_input
|
||||||
|
if [ -n "$hostname_input" ]; then
|
||||||
|
hostname="$hostname_input"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# labels
|
||||||
|
echo -n "Labels? (space separated): " && read -r labels_input
|
||||||
|
if [ -n "$labels_input" ]; then
|
||||||
|
labels="$labels_input"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# location
|
||||||
|
echo -n "Location? (optional): " && read -r location_input
|
||||||
|
if [ -n "$location_input" ]; then
|
||||||
|
location="$location_input"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# clone repo
|
||||||
|
repo1="https://github.com/snowykami/server-status-client"
|
||||||
|
repo2="https://git.liteyuki.icu/snowykami/server-status-client"
|
||||||
|
# try 1 if failed try 2
|
||||||
|
git clone "$repo1" "$install_dir/server-status-client" || git clone "$repo2" "$install_dir/server-status-client"
|
||||||
|
cd "$install_dir/server-status-client" || { echo "Failed to clone repo"; exit 1; }
|
||||||
|
|
||||||
|
# create venv
|
||||||
|
python3 -m venv venv
|
||||||
|
python_exe="./venv/bin/python"
|
||||||
|
|
||||||
|
# check if venv is created
|
||||||
|
if [ ! -f "$python_exe" ]; then
|
||||||
|
echo "Failed to create venv"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "venv created successfully"
|
||||||
|
|
||||||
|
# install the required packages
|
||||||
|
echo "Installing the required packages"
|
||||||
|
$python_exe -m pip install pdm
|
||||||
|
$python_exe -m pdm install
|
||||||
|
|
||||||
|
# create the systemd service
|
||||||
|
echo "Creating the systemd service"
|
||||||
|
|
||||||
|
# generate random id
|
||||||
|
# shellcheck disable=SC2002
|
||||||
|
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]
|
||||||
|
Description=Server Status Client
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=$install_dir/server-status-client/venv/bin/python main.py $server $token $id run -n $hostname --labels $labels --location $location
|
||||||
|
WorkingDirectory=$install_dir/server-status-client
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF"
|
||||||
|
|
||||||
|
# enable and start the service
|
||||||
|
systemctl enable server-status-client
|
||||||
|
systemctl start server-status-client
|
||||||
|
|
||||||
|
echo "server-status-client installed successfully"
|
7
main.py
Normal file
7
main.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from server_status.__main__ import main
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(sys.argv)
|
||||||
|
main()
|
193
pdm.lock
generated
193
pdm.lock
generated
@ -1,193 +0,0 @@
|
|||||||
# This file is @generated by PDM.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
groups = ["default"]
|
|
||||||
strategy = ["inherit_metadata"]
|
|
||||||
lock_version = "4.5.0"
|
|
||||||
content_hash = "sha256:35d8de0fef9028880b4f2f9e77f90ea9296a7760777e2fc1851550bd188977b8"
|
|
||||||
|
|
||||||
[[metadata.targets]]
|
|
||||||
requires_python = ">=3.11"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arclet-alconna"
|
|
||||||
version = "1.8.30"
|
|
||||||
requires_python = ">=3.8"
|
|
||||||
summary = "A High-performance, Generality, Humane Command Line Arguments Parser Library."
|
|
||||||
groups = ["default"]
|
|
||||||
dependencies = [
|
|
||||||
"nepattern<1.0.0,>=0.7.6",
|
|
||||||
"tarina>=0.5.8",
|
|
||||||
"typing-extensions>=4.5.0",
|
|
||||||
]
|
|
||||||
files = [
|
|
||||||
{file = "arclet_alconna-1.8.30-py3-none-any.whl", hash = "sha256:835bf4e8d5deeb78ced2687d49e958a28fe19e39d0fb0fc30d767143d3e41329"},
|
|
||||||
{file = "arclet_alconna-1.8.30.tar.gz", hash = "sha256:cdc064446c0db31285fd2cd4573d7fabe59b81e00e816b9f20f395f1c214b4ac"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "certifi"
|
|
||||||
version = "2024.8.30"
|
|
||||||
requires_python = ">=3.6"
|
|
||||||
summary = "Python package for providing Mozilla's CA Bundle."
|
|
||||||
groups = ["default"]
|
|
||||||
files = [
|
|
||||||
{file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
|
|
||||||
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "charset-normalizer"
|
|
||||||
version = "3.3.2"
|
|
||||||
requires_python = ">=3.7.0"
|
|
||||||
summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
|
||||||
groups = ["default"]
|
|
||||||
files = [
|
|
||||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
|
||||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
|
||||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "idna"
|
|
||||||
version = "3.10"
|
|
||||||
requires_python = ">=3.6"
|
|
||||||
summary = "Internationalized Domain Names in Applications (IDNA)"
|
|
||||||
groups = ["default"]
|
|
||||||
files = [
|
|
||||||
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
|
|
||||||
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nepattern"
|
|
||||||
version = "0.7.6"
|
|
||||||
requires_python = ">=3.8"
|
|
||||||
summary = "a complex pattern, support typing"
|
|
||||||
groups = ["default"]
|
|
||||||
dependencies = [
|
|
||||||
"tarina>=0.5.1",
|
|
||||||
"typing-extensions>=4.5.0",
|
|
||||||
]
|
|
||||||
files = [
|
|
||||||
{file = "nepattern-0.7.6-py3-none-any.whl", hash = "sha256:233d0befecc190f228ded3651a85faaf53f1308bba40ab8ddec379d0d3c88051"},
|
|
||||||
{file = "nepattern-0.7.6.tar.gz", hash = "sha256:07bd5b2f3b9b9739b703bf723ffd642ca93738a32df7b699d57d6f338d46bad0"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "psutil"
|
|
||||||
version = "6.0.0"
|
|
||||||
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
|
|
||||||
summary = "Cross-platform lib for process and system monitoring in Python."
|
|
||||||
groups = ["default"]
|
|
||||||
files = [
|
|
||||||
{file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"},
|
|
||||||
{file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"},
|
|
||||||
{file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"},
|
|
||||||
{file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"},
|
|
||||||
{file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"},
|
|
||||||
{file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"},
|
|
||||||
{file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"},
|
|
||||||
{file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "requests"
|
|
||||||
version = "2.32.3"
|
|
||||||
requires_python = ">=3.8"
|
|
||||||
summary = "Python HTTP for Humans."
|
|
||||||
groups = ["default"]
|
|
||||||
dependencies = [
|
|
||||||
"certifi>=2017.4.17",
|
|
||||||
"charset-normalizer<4,>=2",
|
|
||||||
"idna<4,>=2.5",
|
|
||||||
"urllib3<3,>=1.21.1",
|
|
||||||
]
|
|
||||||
files = [
|
|
||||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
|
||||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tarina"
|
|
||||||
version = "0.5.8"
|
|
||||||
requires_python = ">=3.8"
|
|
||||||
summary = "A collection of common utils for Arclet"
|
|
||||||
groups = ["default"]
|
|
||||||
dependencies = [
|
|
||||||
"typing-extensions>=4.4.0",
|
|
||||||
]
|
|
||||||
files = [
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9b730d605691c1afc074f684b77c12e921d8a0a278b80b5fc016ab2bf75ee081"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:21dfdacf4ca5b46ecfbcd2ea92445abf9aced634aaef285fec8d914163261db8"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3162eace1e5193313f1523a943b5ae14464199782f235e87702da9ee3fb37a6"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:385882a2991046aa05f7b183f386ec2c949076aeacb4acad525ead63342d73f7"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76ee0f135cbe26549592fa12691cb057aa4464d4182c35d7d967361eba52ed95"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2c188c34143ae6bdcee13bac089845f1ca7d32169d85f172091550e0f34fda35"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a45e5f0fccd0267a15582b9d8cfa4b21fca5c1c690ced673f0f58869b98cb178"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-win32.whl", hash = "sha256:e554bd8e22a43ffc8f441d771585e81f90150de2f9e9d9a984c7b004bb613c10"},
|
|
||||||
{file = "tarina-0.5.8-cp311-cp311-win_amd64.whl", hash = "sha256:51c8b7ad1cc114efde36ab09687b5f93afde27ad082cd38721dc327c7f0d922d"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c95f227e7265cfce8c4fb5eebef2a148934b52b782527ded278a4e0926b90ceb"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a394bd75c92d39c0e4c1ee40404de24316f4263f10e296e8d4e19bd0a3c50e55"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9db70e6fb97ee8a87da52e9ced52ee6df7c468f75b72ef98af5a97929e12bc2d"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b713717dcafcd03a86f41509b6c9ebc2749419c9c8c6d559edd6fdfaca6f354"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccaf87a54e062a2d72a60d699198760684aca231c7de7de11d61c191d1e870bf"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a1dc7e8e84ab4e0d6bfb3e4e9c82c7d8a4c002794b7b44010658f0f81e8b5e52"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:dbc6e78e3ee9b24f9c0feb2c14c17d9696098abf6530ae63d6f4158ab7038c38"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-win32.whl", hash = "sha256:4e1a08f1c3d40f935cc8c9507b7ea669b002a53dc7334c9b0ede9f71cf9d1cba"},
|
|
||||||
{file = "tarina-0.5.8-cp312-cp312-win_amd64.whl", hash = "sha256:ab90fd830ec05d5f7cd001906fdd1a3e00d8c9fd221772d02bb87a7aec947925"},
|
|
||||||
{file = "tarina-0.5.8-py3-none-any.whl", hash = "sha256:90740760e9f516677962eff5242a722c616939b123c566a85d7e009ec9868eb3"},
|
|
||||||
{file = "tarina-0.5.8.tar.gz", hash = "sha256:ab5a8b901829242c64a8a0436c7753e894ccae36891ca20a9deda9de6210a0b3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typing-extensions"
|
|
||||||
version = "4.12.2"
|
|
||||||
requires_python = ">=3.8"
|
|
||||||
summary = "Backported and Experimental Type Hints for Python 3.8+"
|
|
||||||
groups = ["default"]
|
|
||||||
files = [
|
|
||||||
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
|
||||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "urllib3"
|
|
||||||
version = "2.2.3"
|
|
||||||
requires_python = ">=3.8"
|
|
||||||
summary = "HTTP library with thread-safe connection pooling, file post, and more."
|
|
||||||
groups = ["default"]
|
|
||||||
files = [
|
|
||||||
{file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"},
|
|
||||||
{file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"},
|
|
||||||
]
|
|
@ -9,8 +9,9 @@ dependencies = [
|
|||||||
"requests>=2.32.3",
|
"requests>=2.32.3",
|
||||||
"psutil>=6.0.0",
|
"psutil>=6.0.0",
|
||||||
"arclet-alconna>=1.8.30",
|
"arclet-alconna>=1.8.30",
|
||||||
|
"pytz>=2024.2",
|
||||||
]
|
]
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.10"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = { text = "MIT" }
|
license = { text = "MIT" }
|
||||||
|
|
||||||
@ -28,3 +29,7 @@ distribution = true
|
|||||||
source = "scm"
|
source = "scm"
|
||||||
tag_filter = "v*"
|
tag_filter = "v*"
|
||||||
tag_regex = '^v(?:\D*)?(?P<version>([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|c|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$)$'
|
tag_regex = '^v(?:\D*)?(?P<version>([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|c|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$)$'
|
||||||
|
|
||||||
|
[[tool.pdm.source]]
|
||||||
|
name = "pypi"
|
||||||
|
url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
|
@ -6,6 +6,7 @@ from server_status.cmd_parser import server_status_alc
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
raw_msg = "server_status " + " ".join(sys.argv[1:])
|
raw_msg = "server_status " + " ".join(sys.argv[1:])
|
||||||
|
print(raw_msg)
|
||||||
arp = server_status_alc.parse(raw_msg)
|
arp = server_status_alc.parse(raw_msg)
|
||||||
|
|
||||||
if arp.query("run"):
|
if arp.query("run"):
|
||||||
|
@ -6,6 +6,44 @@ from typing import Any
|
|||||||
import psutil
|
import psutil
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from server_status.timezone import get_timezone
|
||||||
|
|
||||||
|
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):
|
def log(*args):
|
||||||
# 在输出前加上时间
|
# 在输出前加上时间
|
||||||
@ -25,6 +63,7 @@ def get_network_speed(interval) -> tuple[int, int]:
|
|||||||
|
|
||||||
|
|
||||||
class Hardware:
|
class Hardware:
|
||||||
|
os_release: str = ""
|
||||||
mem_total: int = psutil.virtual_memory().total
|
mem_total: int = psutil.virtual_memory().total
|
||||||
mem_used: int = psutil.virtual_memory().used
|
mem_used: int = psutil.virtual_memory().used
|
||||||
|
|
||||||
@ -37,6 +76,8 @@ class Hardware:
|
|||||||
|
|
||||||
disks: dict[str, dict[str, int]] = {}
|
disks: dict[str, dict[str, int]] = {}
|
||||||
|
|
||||||
|
timezone: str = get_timezone()
|
||||||
|
|
||||||
net_up: int = 0
|
net_up: int = 0
|
||||||
net_down: int = 0
|
net_down: int = 0
|
||||||
net_type: str = "ethernet"
|
net_type: str = "ethernet"
|
||||||
@ -106,7 +147,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):
|
||||||
@ -119,8 +162,17 @@ class Api:
|
|||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self, addr: str, token: str, client_id: str, name: str = "", location: str = "", labels: list[str] = [], link: str = "",
|
def __init__(
|
||||||
interval: int = 5):
|
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 = 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}")
|
||||||
@ -134,15 +186,66 @@ class Client:
|
|||||||
self.link = link
|
self.link = link
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
|
|
||||||
|
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.start_time = time.time()
|
log("Starting client")
|
||||||
self.observe()
|
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:
|
while True:
|
||||||
try:
|
try:
|
||||||
resp = self.get_ping()
|
resp = self.get_ping()
|
||||||
@ -150,9 +253,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:
|
||||||
@ -179,14 +286,19 @@ class Client:
|
|||||||
"id": self.client_id,
|
"id": self.client_id,
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"os": {
|
"os": {
|
||||||
"name": platform.system(),
|
"name": platform.system(), # 系统类型 linux|windows|darwin
|
||||||
"version": platform.version(),
|
"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,
|
"labels": self.labels,
|
||||||
"location": self.location,
|
"location": self.location,
|
||||||
"uptime": int(time.time() - self.start_time),
|
"uptime": int(time.time() - self.start_time),
|
||||||
|
"start_time": int(self.start_time), # 系统启动的时间
|
||||||
"link": self.link,
|
"link": self.link,
|
||||||
"observed_at": int(time.time()),
|
"observed_at": int(time.time()),
|
||||||
|
"timezone": self.hardware.timezone,
|
||||||
},
|
},
|
||||||
"hardware": {
|
"hardware": {
|
||||||
"mem": {
|
"mem": {
|
||||||
@ -211,35 +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()
|
|
||||||
self.hardware.cpu_logics = psutil.cpu_count(logical=True)
|
|
||||||
for part in psutil.disk_partitions():
|
|
||||||
try:
|
|
||||||
usage = psutil.disk_usage(part.mountpoint)
|
|
||||||
self.hardware.disks[part.device] = {
|
|
||||||
"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:
|
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})
|
||||||
|
@ -3,7 +3,7 @@ import socket
|
|||||||
|
|
||||||
from arclet.alconna import Alconna, Subcommand, Option, Args, MultiVar
|
from arclet.alconna import Alconna, Subcommand, Option, Args, MultiVar
|
||||||
|
|
||||||
server_status_alc = Alconna(
|
server_status_alc = Alconna( # type: ignore
|
||||||
"server_status",
|
"server_status",
|
||||||
Args["server", str]["token", str]["id", str],
|
Args["server", str]["token", str]["id", str],
|
||||||
Subcommand(
|
Subcommand(
|
||||||
|
136
server_status/timezone.py
Normal file
136
server_status/timezone.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import os
|
||||||
|
import platform
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
windows_timezone_map = {
|
||||||
|
"Dateline Standard Time": "Etc/GMT+12",
|
||||||
|
"UTC-11": "Etc/GMT+11",
|
||||||
|
"Aleutian Standard Time": "America/Adak",
|
||||||
|
"Hawaiian Standard Time": "Pacific/Honolulu",
|
||||||
|
"Marquesas Standard Time": "Pacific/Marquesas",
|
||||||
|
"Alaskan Standard Time": "America/Anchorage",
|
||||||
|
"UTC-09": "Etc/GMT+9",
|
||||||
|
"Pacific Standard Time (Mexico)": "America/Tijuana",
|
||||||
|
"UTC-08": "Etc/GMT+8",
|
||||||
|
"Pacific Standard Time": "America/Los_Angeles",
|
||||||
|
"US Mountain Standard Time": "America/Phoenix",
|
||||||
|
"Mountain Standard Time (Mexico)": "America/Chihuahua",
|
||||||
|
"Mountain Standard Time": "America/Denver",
|
||||||
|
"Central America Standard Time": "America/Guatemala",
|
||||||
|
"Central Standard Time": "America/Chicago",
|
||||||
|
"Easter Island Standard Time": "Pacific/Easter",
|
||||||
|
"Central Standard Time (Mexico)": "America/Mexico_City",
|
||||||
|
"Canada Central Standard Time": "America/Regina",
|
||||||
|
"SA Pacific Standard Time": "America/Bogota",
|
||||||
|
"Eastern Standard Time (Mexico)": "America/Cancun",
|
||||||
|
"Eastern Standard Time": "America/New_York",
|
||||||
|
"Haiti Standard Time": "America/Port-au-Prince",
|
||||||
|
"Cuba Standard Time": "America/Havana",
|
||||||
|
"US Eastern Standard Time": "America/Indianapolis",
|
||||||
|
"Turks And Caicos Standard Time": "America/Grand_Turk",
|
||||||
|
"Paraguay Standard Time": "America/Asuncion",
|
||||||
|
"Atlantic Standard Time": "America/Halifax",
|
||||||
|
"Venezuela Standard Time": "America/Caracas",
|
||||||
|
"Central Brazilian Standard Time": "America/Cuiaba",
|
||||||
|
"SA Western Standard Time": "America/La_Paz",
|
||||||
|
"Pacific SA Standard Time": "America/Santiago",
|
||||||
|
"SA Eastern Standard Time": "America/Cayenne",
|
||||||
|
"Argentina Standard Time": "America/Buenos_Aires",
|
||||||
|
"Greenland Standard Time": "America/Godthab",
|
||||||
|
"Montevideo Standard Time": "America/Montevideo",
|
||||||
|
"Bahia Standard Time": "America/Bahia",
|
||||||
|
"UTC-02": "Etc/GMT+2",
|
||||||
|
"Azores Standard Time": "Atlantic/Azores",
|
||||||
|
"Cape Verde Standard Time": "Atlantic/Cape_Verde",
|
||||||
|
"UTC": "Etc/GMT",
|
||||||
|
"GMT Standard Time": "Europe/London",
|
||||||
|
"Greenwich Standard Time": "Atlantic/Reykjavik",
|
||||||
|
"W. Europe Standard Time": "Europe/Berlin",
|
||||||
|
"Central Europe Standard Time": "Europe/Budapest",
|
||||||
|
"Romance Standard Time": "Europe/Paris",
|
||||||
|
"Central European Standard Time": "Europe/Warsaw",
|
||||||
|
"W. Central Africa Standard Time": "Africa/Lagos",
|
||||||
|
"Namibia Standard Time": "Africa/Windhoek",
|
||||||
|
"GTB Standard Time": "Europe/Bucharest",
|
||||||
|
"Middle East Standard Time": "Asia/Beirut",
|
||||||
|
"Egypt Standard Time": "Africa/Cairo",
|
||||||
|
"Syria Standard Time": "Asia/Damascus",
|
||||||
|
"E. Europe Standard Time": "Europe/Chisinau",
|
||||||
|
"South Africa Standard Time": "Africa/Johannesburg",
|
||||||
|
"FLE Standard Time": "Europe/Kiev",
|
||||||
|
"Turkey Standard Time": "Europe/Istanbul",
|
||||||
|
"Israel Standard Time": "Asia/Jerusalem",
|
||||||
|
"Jordan Standard Time": "Asia/Amman",
|
||||||
|
"Arabic Standard Time": "Asia/Riyadh",
|
||||||
|
"Kaliningrad Standard Time": "Europe/Kaliningrad",
|
||||||
|
"Arab Standard Time": "Asia/Riyadh",
|
||||||
|
"E. Africa Standard Time": "Africa/Nairobi",
|
||||||
|
"Iran Standard Time": "Asia/Tehran",
|
||||||
|
"Arabian Standard Time": "Asia/Dubai",
|
||||||
|
"Astrakhan Standard Time": "Europe/Astrakhan",
|
||||||
|
"Russian Standard Time": "Europe/Moscow",
|
||||||
|
"E. Europe Standard Time": "Europe/Chisinau",
|
||||||
|
"W. Australia Standard Time": "Australia/Perth",
|
||||||
|
"Moscow Standard Time": "Europe/Moscow",
|
||||||
|
"Pakistan Standard Time": "Asia/Karachi",
|
||||||
|
"India Standard Time": "Asia/Kolkata",
|
||||||
|
"Sri Lanka Standard Time": "Asia/Colombo",
|
||||||
|
"Nepal Standard Time": "Asia/Kathmandu",
|
||||||
|
"Bangladesh Standard Time": "Asia/Dhaka",
|
||||||
|
"Afghanistan Standard Time": "Asia/Kabul",
|
||||||
|
"Myanmar Standard Time": "Asia/Yangon",
|
||||||
|
"SE Asia Standard Time": "Asia/Bangkok",
|
||||||
|
"North Asia Standard Time": "Asia/Krasnoyarsk",
|
||||||
|
"China Standard Time": "Asia/Shanghai",
|
||||||
|
"Singapore Standard Time": "Asia/Singapore",
|
||||||
|
"W. Australia Standard Time": "Australia/Perth",
|
||||||
|
"Taipei Standard Time": "Asia/Taipei",
|
||||||
|
"Ulaanbaatar Standard Time": "Asia/Ulaanbaatar",
|
||||||
|
"North Asia East Standard Time": "Asia/Irkutsk",
|
||||||
|
"Korea Standard Time": "Asia/Seoul",
|
||||||
|
"Tokyo Standard Time": "Asia/Tokyo",
|
||||||
|
"Yakutsk Standard Time": "Asia/Yakutsk",
|
||||||
|
"Cen. Australia Standard Time": "Australia/Adelaide",
|
||||||
|
"AUS Central Standard Time": "Australia/Darwin",
|
||||||
|
"E. Australia Standard Time": "Australia/Brisbane",
|
||||||
|
"AUS Eastern Standard Time": "Australia/Sydney",
|
||||||
|
"West Pacific Standard Time": "Pacific/Port_Moresby",
|
||||||
|
"Tasmania Standard Time": "Australia/Hobart",
|
||||||
|
"Magadan Standard Time": "Asia/Magadan",
|
||||||
|
"Vladivostok Standard Time": "Asia/Vladivostok",
|
||||||
|
"Russia Time Zone 10": "Asia/Srednekolymsk",
|
||||||
|
"Central Pacific Standard Time": "Pacific/Guadalcanal",
|
||||||
|
"Fiji Standard Time": "Pacific/Fiji",
|
||||||
|
"New Zealand Standard Time": "Pacific/Auckland",
|
||||||
|
"UTC+12": "Etc/GMT-12",
|
||||||
|
"Kamchatka Standard Time": "Asia/Kamchatka",
|
||||||
|
"Tonga Standard Time": "Pacific/Tongatapu",
|
||||||
|
"Samoa Standard Time": "Pacific/Apia",
|
||||||
|
"Line Islands Standard Time": "Pacific/Kiritimati",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_timezone() -> str:
|
||||||
|
try:
|
||||||
|
# 尝试获取系统的本地时区
|
||||||
|
if 'TZ' in os.environ:
|
||||||
|
return os.environ['TZ']
|
||||||
|
|
||||||
|
# 如果环境变量中没有TZ,尝试获取系统时区
|
||||||
|
if platform.system() == "Linux":
|
||||||
|
# Linux:
|
||||||
|
with open("/etc/timezone", "r") as f:
|
||||||
|
return f.read().strip()
|
||||||
|
elif platform.system() == "Darwin":
|
||||||
|
# macOS:
|
||||||
|
return ZoneInfo.from_file(open("/etc/localtime")).key
|
||||||
|
elif platform.system() == "Windows":
|
||||||
|
# Windows:
|
||||||
|
import winreg
|
||||||
|
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation") as key:
|
||||||
|
tz = winreg.QueryValueEx(key, "TimeZoneKeyName")[0]
|
||||||
|
return windows_timezone_map.get(tz) or tz
|
||||||
|
else:
|
||||||
|
return "UTC"
|
||||||
|
except Exception as e:
|
||||||
|
return "UTC"
|
Loading…
x
Reference in New Issue
Block a user