mirror of
https://github.com//cppla/ServerStatus
synced 2025-12-15 02:02:04 +08:00
Compare commits
210 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d242c6cea1 | ||
|
|
d7614ab168 | ||
|
|
ff06df8263 | ||
|
|
9ee1516f72 | ||
|
|
7603ce37af | ||
|
|
5cfd533daf | ||
|
|
9077f1058a | ||
|
|
e34ed05901 | ||
|
|
4ab545f646 | ||
|
|
a6b4248967 | ||
|
|
8ad927d88d | ||
|
|
4b1ec57c6d | ||
|
|
979a9b5d87 | ||
|
|
52d62afa59 | ||
|
|
806b60bd6b | ||
|
|
d5af5445df | ||
|
|
c77e00476c | ||
|
|
b551998eb8 | ||
|
|
1c606cc79e | ||
|
|
d602791b11 | ||
|
|
a695ef8b3a | ||
|
|
9f60b7962b | ||
|
|
34b1bca5b1 | ||
|
|
25917f0883 | ||
|
|
333bc29c88 | ||
|
|
c116067c39 | ||
|
|
14db7ec943 | ||
|
|
af8244f1d7 | ||
|
|
1004c9a6bd | ||
|
|
7f78af03f0 | ||
|
|
02bbdb18de | ||
|
|
6d813f932d | ||
|
|
19d6a5ea8b | ||
|
|
35de279e89 | ||
|
|
d5a047c781 | ||
|
|
10872059c5 | ||
|
|
44656e565f | ||
|
|
78c7da7361 | ||
|
|
b5edeea057 | ||
|
|
c2259f347d | ||
|
|
bb5f03047d | ||
|
|
6ab6e16d0f | ||
|
|
615cec88c2 | ||
|
|
94896bac80 | ||
|
|
a788b5da90 | ||
|
|
de0bc9dd74 | ||
|
|
ec16fc1fac | ||
|
|
cbd803b686 | ||
|
|
3eddb27d51 | ||
|
|
522809483e | ||
|
|
9d706f4da8 | ||
|
|
a0fe8ee33c | ||
|
|
c5eed8e4fa | ||
|
|
32d302580e | ||
|
|
b03d090a5c | ||
|
|
6151806141 | ||
|
|
2703993272 | ||
|
|
022e5edb28 | ||
|
|
135eb180c8 | ||
|
|
2ead43a0d8 | ||
|
|
baae11de3b | ||
|
|
2e62ffa593 | ||
|
|
f70705d872 | ||
|
|
7316dbdddb | ||
|
|
a1689acbf0 | ||
|
|
e2a59a5465 | ||
|
|
962d564c80 | ||
|
|
77973a5309 | ||
|
|
a9128b137d | ||
|
|
0a2a007e24 | ||
|
|
ab5d6f7d2d | ||
|
|
dae7c07772 | ||
|
|
14447399a0 | ||
|
|
3327c5fd25 | ||
|
|
217b14bf55 | ||
|
|
d7b8f27082 | ||
|
|
8f3736e4fc | ||
|
|
22c1905acb | ||
|
|
f73970262b | ||
|
|
f45d9be9fc | ||
|
|
cb1313f5b5 | ||
|
|
b3f7ab45c5 | ||
|
|
54451cab85 | ||
|
|
0f26eb502a | ||
|
|
472196d1ea | ||
|
|
7e84c230e6 | ||
|
|
76cc15e84f | ||
|
|
4c0f4b94e8 | ||
|
|
36040be11e | ||
|
|
776ad68392 | ||
|
|
39c92f4788 | ||
|
|
6a15832966 | ||
|
|
654ecd7a3e | ||
|
|
47cf7a1818 | ||
|
|
5176cb0340 | ||
|
|
1f47bcdb6f | ||
|
|
7698ce0e4b | ||
|
|
2d457c66ad | ||
|
|
d8c8d8fd3f | ||
|
|
d64beb7ba8 | ||
|
|
30f9999fc6 | ||
|
|
c46d0c06cd | ||
|
|
589c8812de | ||
|
|
110a2d97d8 | ||
|
|
0914175200 | ||
|
|
830ea094a3 | ||
|
|
2f4611bdd8 | ||
|
|
0b9e747cc9 | ||
|
|
22847aa590 | ||
|
|
e8482bf8ac | ||
|
|
be95052d8f | ||
|
|
4c8006d183 | ||
|
|
f1559bfb55 | ||
|
|
cab0f8bc91 | ||
|
|
4e1e92e406 | ||
|
|
fcb4b3cdfe | ||
|
|
260b7b3a21 | ||
|
|
64c028f9ce | ||
|
|
ec4218f1b0 | ||
|
|
00bc87c2c2 | ||
|
|
f36b4e66d2 | ||
|
|
3871c2c3d9 | ||
|
|
4a0b15b61d | ||
|
|
e4fdacb2b5 | ||
|
|
d1bdec5e30 | ||
|
|
d0f3507add | ||
|
|
a3dab0dc0f | ||
|
|
050a6f78dc | ||
|
|
0219d21ad5 | ||
|
|
fc977367ba | ||
|
|
7d02f16fff | ||
|
|
4792821e8e | ||
|
|
6c926209bd | ||
|
|
e274b09c0f | ||
|
|
5078381215 | ||
|
|
4e175d0a81 | ||
|
|
0dc82096f5 | ||
|
|
43c1c1279f | ||
|
|
ef0229b2d7 | ||
|
|
77443663d6 | ||
|
|
4c2bcfbe20 | ||
|
|
8e06385152 | ||
|
|
cc5aec11ba | ||
|
|
7bf4a22457 | ||
|
|
f68d3a8963 | ||
|
|
0834ff138d | ||
|
|
cbbd71d037 | ||
|
|
614c6d323c | ||
|
|
e6d9edee2d | ||
|
|
e00a374f03 | ||
|
|
feef07a6d8 | ||
|
|
a83a2ff5a3 | ||
|
|
8925de8fc9 | ||
|
|
700287125a | ||
|
|
ec86ae7ed8 | ||
|
|
0254971ec7 | ||
|
|
4966fe7daa | ||
|
|
e5d22ad2db | ||
|
|
b348032855 | ||
|
|
3cb0ea4777 | ||
|
|
f6cfdc9e6b | ||
|
|
47a9ba60cb | ||
|
|
37dc23ee45 | ||
|
|
ff51c48c93 | ||
|
|
3edefd45ce | ||
|
|
bde340a7e8 | ||
|
|
5323b28304 | ||
|
|
28f61460c3 | ||
|
|
fd382957ca | ||
|
|
c0ea66171a | ||
|
|
ab0a19b244 | ||
|
|
d6878854b1 | ||
|
|
3aac3ccd0d | ||
|
|
87824ce25a | ||
|
|
9d2a2e1c94 | ||
|
|
6ee766df87 | ||
|
|
5afdb61e88 | ||
|
|
9592ba7b1d | ||
|
|
ecf19ae3c0 | ||
|
|
c512ede1f7 | ||
|
|
45a0723bea | ||
|
|
b8a717a374 | ||
|
|
3f0790db81 | ||
|
|
8acb6ec0df | ||
|
|
7486919dbe | ||
|
|
6188192951 | ||
|
|
e50ca41061 | ||
|
|
dc06c90e94 | ||
|
|
dcb2246d94 | ||
|
|
20d938401c | ||
|
|
87895de2cf | ||
|
|
427303d9ae | ||
|
|
e2f4714641 | ||
|
|
34236b4c5f | ||
|
|
474e7addc9 | ||
|
|
4c042a3fc7 | ||
|
|
a0842a020b | ||
|
|
c98dc92256 | ||
|
|
60264204cb | ||
|
|
e145feb1cd | ||
|
|
2359890ca0 | ||
|
|
430bf2d2e0 | ||
|
|
cfd472357f | ||
|
|
895206baa4 | ||
|
|
1828a476f7 | ||
|
|
7cf9d969bc | ||
|
|
55ee9ca6fb | ||
|
|
9601ef1655 | ||
|
|
a77f94c8d6 | ||
|
|
ab65e0fc26 |
29
Dockerfile
Normal file
29
Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
||||
# The Dockerfile for build localhost source, not git repo
|
||||
FROM debian:buster as builder
|
||||
|
||||
MAINTAINER cppla https://cpp.la
|
||||
|
||||
RUN apt-get update -y && apt-get -y install gcc g++ make libcurl4-openssl-dev
|
||||
|
||||
COPY . .
|
||||
|
||||
WORKDIR /server
|
||||
|
||||
RUN make -j
|
||||
RUN pwd && ls -a
|
||||
|
||||
# glibc env run
|
||||
FROM nginx:latest
|
||||
|
||||
RUN mkdir -p /ServerStatus/server/
|
||||
|
||||
COPY --from=builder server /ServerStatus/server/
|
||||
COPY --from=builder web /usr/share/nginx/html/
|
||||
|
||||
# china time
|
||||
ENV TZ=Asia/Shanghai
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
EXPOSE 80 35601
|
||||
|
||||
CMD nohup sh -c '/etc/init.d/nginx start && /ServerStatus/server/sergate --config=/ServerStatus/server/config.json --web-dir=/usr/share/nginx/html'
|
||||
191
README.md
191
README.md
@@ -3,138 +3,179 @@
|
||||
* ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。
|
||||
* 在线演示:https://tz.cloudcpp.com
|
||||
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
|
||||

|
||||

|
||||
|
||||
# 目录介绍:
|
||||
`Watchdog🐶已经加入,触发式告警。 interval只是为了防止频繁收到报警信息造成骚扰,并不是探测间隔。`
|
||||
|
||||
* autodeploy 自动部署.
|
||||
* clients 客户端文件
|
||||
* server 服务端文件
|
||||
* web 网站文件
|
||||
# 目录:
|
||||
|
||||
# 自动部署:
|
||||
* clients 客户端文件
|
||||
* server 服务端文件
|
||||
* web 网站文件
|
||||
|
||||
* server/config.json 探针配置文件
|
||||
* web/json 探针月流量
|
||||
|
||||
# 部署:
|
||||
|
||||
【服务端】:
|
||||
```bash
|
||||
`x86_64`: docker pull cppla/serverstatus:latest
|
||||
`arm64`: docker pull cppla/serverstatus:arm
|
||||
|
||||
`Docker`:
|
||||
|
||||
wget https://raw.githubusercontent.com/cppla/ServerStatus/master/autodeploy/config.json
|
||||
docker run -d --restart=always --name=serverstatus -v {$path}/config.json:/ServerStatus/server/config.json -p {$port}:80 -p {$port}:35601 cppla/serverstatus:latest
|
||||
wget --no-check-certificate -qO ~/serverstatus-config.json https://raw.githubusercontent.com/cppla/ServerStatus/master/server/config.json && mkdir ~/serverstatus-monthtraffic
|
||||
docker run -d --restart=always --name=serverstatus -v ~/serverstatus-config.json:/ServerStatus/server/config.json -v ~/serverstatus-monthtraffic:/usr/share/nginx/html/json -p 80:80 -p 35601:35601 cppla/serverstatus:latest
|
||||
|
||||
eg:
|
||||
docker run -d --restart=always --name=serverstatus -v ~/config.json:/ServerStatus/server/config.json -p 80:80 -p 35601:35601 cppla/serverstatus:latest
|
||||
|
||||
`Docker-compose(推荐)`: docker-compose up -d
|
||||
```
|
||||
|
||||
【客户端】:
|
||||
```bash
|
||||
wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python client-linux.py SERVER={$SERVER} USER={$USER} PASSWORD={$PASSWORD} >/dev/null 2>&1 &
|
||||
wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python3 client-linux.py SERVER={$SERVER} USER={$USER} PASSWORD={$PASSWORD} >/dev/null 2>&1 &
|
||||
|
||||
eg:
|
||||
wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python client-linux.py SERVER=45.79.67.132 USER=s04 >/dev/null 2>&1 &
|
||||
wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python3 client-linux.py SERVER=45.79.67.132 USER=s04 >/dev/null 2>&1 &
|
||||
```
|
||||
|
||||
# 主题:
|
||||
|
||||
* layui:https://github.com/zeyudada/StatusServerLayui ,预览:https://sslt.8zyw.cn
|
||||
<img src=https://dl.cpp.la/Archive/serverstatus_layui.png width=200 height=100 />
|
||||
|
||||
* light:https://github.com/orilights/ServerStatus-Theme-Light ,预览:https://tz.cloudcpp.com/index3.html
|
||||
<img src=https://github.com/orilights/ServerStatus-Theme-Light/blob/main/docs/screenshot.png width=200 height=100 />
|
||||
|
||||
|
||||
# 手动安装教程:
|
||||
|
||||
【克隆代码】:
|
||||
```
|
||||
git clone https://github.com/cppla/ServerStatus.git
|
||||
```
|
||||
|
||||
【服务端配置】(服务端程序在ServerStatus/web下):
|
||||
**【服务端配置】**
|
||||
|
||||
一、生成服务端程序
|
||||
#### 一、生成服务端程序
|
||||
```
|
||||
cd ServerStatus/server
|
||||
make
|
||||
`Debian/Ubuntu`: apt-get -y install gcc g++ make libcurl4-openssl-dev
|
||||
`Centos/Redhat`: yum -y install gcc gcc-c++ make libcurl-devel
|
||||
|
||||
cd ServerStatus/server && make
|
||||
./sergate
|
||||
```
|
||||
如果没错误提示,OK,ctrl+c关闭;如果有错误提示,检查35601端口是否被占用
|
||||
|
||||
二、修改配置文件
|
||||
修改config.json文件,注意username, password的值需要和客户端对应一致
|
||||
#### 二、修改配置文件
|
||||
```diff
|
||||
! watchdog rule 可以为任何已知字段的表达式。
|
||||
! watchdog interval 最小通知间隔。
|
||||
! watchdog callback 可自定义为Post方法的URL,告警内容将拼接其后并发起回调。
|
||||
|
||||
! watchdog callback Telegram: https://api.telegram.org/bot你自己的密钥/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=你自己的标识&text=
|
||||
! watchdog callback Server酱: https://sctapi.ftqq.com/你自己的密钥.send?title=ServerStatus&desp=
|
||||
! watchdog callback PushDeer: https://api2.pushdeer.com/message/push?pushkey=你自己的密钥&text=
|
||||
! watchdog callback BasicAuth: https://用户名:密码@你自己的域名/api/push?message=
|
||||
```
|
||||
{"servers":
|
||||
|
||||
```
|
||||
{
|
||||
"servers":
|
||||
[
|
||||
{
|
||||
"username": "s01",
|
||||
"name": "Mainserver 1",
|
||||
"type": "Dedicated Server",
|
||||
"host": "GenericServerHost123",
|
||||
"location": "Austria",
|
||||
"password": "some-hard-to-guess-copy-paste-password"
|
||||
"name": "vps-1",
|
||||
"type": "kvm",
|
||||
"host": "chengdu",
|
||||
"location": "🇨🇳",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1
|
||||
},
|
||||
],
|
||||
"watchdog":
|
||||
[
|
||||
{
|
||||
"name": "服务器负载高监控",
|
||||
"rule": "cpu>90&load_5>3",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器内存使用率过高监控",
|
||||
"rule": "(memory_used/memory_total)*100>90",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器宕机告警,排除经常掉线的",
|
||||
"rule": "online4=0&online6=0&username!=s21",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "DDOS和CC攻击监控",
|
||||
"rule": "tcp_count>600",
|
||||
"interval": 300,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器月出口流量999GB告警",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "你可以组合任何已知字段的表达式",
|
||||
"rule": "(hdd_used/hdd_total)*100>95",
|
||||
"interval": 1800,
|
||||
"callback": "https://yourSMSurl"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
三、拷贝ServerStatus/status到你的网站目录
|
||||
#### 三、拷贝ServerStatus/status到你的网站目录
|
||||
例如:
|
||||
```
|
||||
sudo cp -r ServerStatus/web/* /home/wwwroot/default
|
||||
```
|
||||
|
||||
四、运行服务端:
|
||||
#### 四、运行服务端:
|
||||
web-dir参数为上一步设置的网站根目录,务必修改成自己网站的路径
|
||||
```
|
||||
./sergate --config=config.json --web-dir=/home/wwwroot/default
|
||||
```
|
||||
|
||||
【客户端配置】(客户端程序在ServerStatus/clients下):
|
||||
**【客户端配置】**
|
||||
|
||||
客户端有两个版本,client-linux为普通linux,client-psutil为跨平台版,普通版不成功,换成跨平台版即可。
|
||||
|
||||
一、client-linux版配置:
|
||||
#### 一、client-linux版配置:
|
||||
1、vim client-linux.py, 修改SERVER地址,username帐号, password密码
|
||||
2、python client-linux.py 运行即可。
|
||||
2、python3 client-linux.py 运行即可。
|
||||
|
||||
二、client-psutil版配置:
|
||||
1、安装psutil跨平台依赖库
|
||||
#### 二、client-psutil版配置:
|
||||
1、安装psutil跨平台依赖库
|
||||
```
|
||||
`Debian/Ubuntu`: apt -y install python3-pip && pip3 install psutil
|
||||
`Centos/Redhat`: yum -y install python3-pip gcc python3-devel && pip3 install psutil
|
||||
`Windows`: https://pypi.org/project/psutil/
|
||||
```
|
||||
2、vim client-psutil.py, 修改SERVER地址,username帐号, password密码
|
||||
3、python client-psutil.py 运行即可。
|
||||
```
|
||||
### for Centos:
|
||||
sudo yum -y install epel-release
|
||||
sudo yum -y install python-pip
|
||||
sudo yum clean all
|
||||
sudo yum -y install gcc
|
||||
sudo yum -y install python-devel
|
||||
sudo pip install psutil
|
||||
### for Ubuntu/Debian:
|
||||
sudo root
|
||||
apt-get -y install python-setuptools python-dev build-essential
|
||||
apt-get -y install python-pip
|
||||
pip install psutil
|
||||
### for Windows:
|
||||
打开网址:https://pypi.python.org/pypi?:action=display&name=psutil#downloads
|
||||
下载psutil for windows程序包
|
||||
安装即可
|
||||
```
|
||||
3、python3 client-psutil.py 运行即可。
|
||||
|
||||
打开云探针页面,就可以正常的监控。接下来把服务器和客户端脚本自行加入开机启动,或者进程守护,或以后台方式运行即可!例如: nohup python client-linux.py &
|
||||
服务器和客户端自行加入开机启动,或进程守护,或后台方式运行。 例如: nohup python3 client-linux.py &
|
||||
|
||||
### 如何快速跟随系统启动呢?其实好多人都搞复杂化了
|
||||
1、chmod 755 /root/client-linux.py
|
||||
2、vim /etc/crontab,尾部追加
|
||||
```diff
|
||||
@reboot root /root/client-linux.py SERVER=$server USER=$user
|
||||
```
|
||||
`extra scene (run web/ssview.py)`
|
||||

|
||||
|
||||
# 为什么会有ServerStatus中文版:
|
||||
|
||||
* 有些功能确实没用
|
||||
* 原版本部署,英文说明复杂
|
||||
* 不符合中文版的习惯
|
||||
* 没有一次又一次的轮子,哪来如此优秀的云探针
|
||||
# Make Better
|
||||
|
||||
# 相关开源项目,感谢:
|
||||
|
||||
* ServerStatus:https://github.com/BotoX/ServerStatus
|
||||
* BotoX:https://github.com/BotoX/ServerStatus
|
||||
* mojeda: https://github.com/mojeda
|
||||
* mojeda's ServerStatus: https://github.com/mojeda/ServerStatus
|
||||
* BlueVM's project: http://www.lowendtalk.com/discussion/comment/169690#Comment_169690
|
||||
|
||||
# Jetbrains
|
||||
|
||||
<a href="https://www.jetbrains.com/?from=ServerStatus"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_square.png" width="100px"></a>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
FROM debian:latest as builder
|
||||
|
||||
MAINTAINER cppla https://cpp.la
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install gcc g++ make git
|
||||
RUN git clone https://github.com/cppla/ServerStatus
|
||||
|
||||
WORKDIR /ServerStatus/server
|
||||
|
||||
RUN make
|
||||
RUN pwd && ls -a
|
||||
|
||||
# glibc env run
|
||||
FROM nginx:latest
|
||||
|
||||
RUN mkdir -p /ServerStatus/server/
|
||||
|
||||
COPY --from=builder /ServerStatus/server /ServerStatus/server/
|
||||
COPY --from=builder /ServerStatus/web /usr/share/nginx/html/
|
||||
|
||||
EXPOSE 80 35601
|
||||
|
||||
CMD nohup sh -c '/etc/init.d/nginx start && /ServerStatus/server/sergate --config=/ServerStatus/server/config.json --web-dir=/usr/share/nginx/html'
|
||||
@@ -1,37 +0,0 @@
|
||||
{"servers":
|
||||
[
|
||||
{
|
||||
"username": "s01",
|
||||
"name": "node1",
|
||||
"type": "xen",
|
||||
"host": "host1",
|
||||
"location": "cn",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
},
|
||||
{
|
||||
"username": "s02",
|
||||
"name": "node2",
|
||||
"type": "vmware",
|
||||
"host": "host2",
|
||||
"location": "jp",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"username": "s03",
|
||||
"name": "node3",
|
||||
"type": "Nothing",
|
||||
"host": "host3",
|
||||
"location": "fr",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
},
|
||||
{
|
||||
"username": "s04",
|
||||
"name": "ssss",
|
||||
"type": "ssss",
|
||||
"host": "ssss",
|
||||
"location": "ssss",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
服务端:
|
||||
|
||||
docker build -f Dockerfile -t sss .
|
||||
docker run -d --restart=always --name=sss -v {$path}/config.json:/ServerStatus/server/config.json -p {$port}:80 -p {$port}:35601 sss
|
||||
|
||||
客户端:
|
||||
|
||||
wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python client-linux.py SERVER={$SERVER} USER={$USER} PASSWORD={$PASSWORD} >/dev/null 2>&1 &
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
附: docker安装
|
||||
curl -sSL https://get.docker.com/ | sh
|
||||
@@ -1,25 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
# Update by : https://github.com/cppla/ServerStatus
|
||||
# 支持Python版本:2.7 to 3.7
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20220530
|
||||
# 版本:1.0.3, 支持Python版本:2.7 to 3.10
|
||||
# 支持操作系统: Linux, OSX, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
# 时间: 20200407
|
||||
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
|
||||
|
||||
SERVER = "127.0.0.1"
|
||||
USER = "s01"
|
||||
|
||||
|
||||
|
||||
PORT = 35601
|
||||
PASSWORD = "USER_DEFAULT_PASSWORD"
|
||||
INTERVAL = 1
|
||||
PROBEPORT = 80
|
||||
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
|
||||
PING_PACKET_HISTORY_LEN = 100
|
||||
PORT = 35601
|
||||
CU = "cu.tz.cloudcpp.com"
|
||||
CT = "ct.tz.cloudcpp.com"
|
||||
CM = "cm.tz.cloudcpp.com"
|
||||
PROBEPORT = 80
|
||||
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
|
||||
PING_PACKET_HISTORY_LEN = 100
|
||||
INTERVAL = 1
|
||||
|
||||
import socket
|
||||
import time
|
||||
@@ -119,18 +117,6 @@ def tupd():
|
||||
d = int(s[:-1])-2
|
||||
return t,u,p,d
|
||||
|
||||
def ip_status():
|
||||
ip_check = 0
|
||||
for i in [CU, CT, CM]:
|
||||
try:
|
||||
socket.create_connection((i, PROBEPORT), timeout=1).close()
|
||||
except:
|
||||
ip_check += 1
|
||||
if ip_check >= 2:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_network(ip_version):
|
||||
if(ip_version == 4):
|
||||
HOST = "ipv4.google.com"
|
||||
@@ -160,22 +146,27 @@ netSpeed = {
|
||||
'avgrx': 0,
|
||||
'avgtx': 0
|
||||
}
|
||||
diskIO = {
|
||||
'read': 0,
|
||||
'write': 0
|
||||
}
|
||||
|
||||
def _ping_thread(host, mark, port):
|
||||
lostPacket = 0
|
||||
packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN)
|
||||
|
||||
IP = host
|
||||
if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname
|
||||
try:
|
||||
if PROBE_PROTOCOL_PREFER == 'ipv4':
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0]
|
||||
else:
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
|
||||
except Exception:
|
||||
while True:
|
||||
# flush dns , every time.
|
||||
IP = host
|
||||
if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname
|
||||
try:
|
||||
if PROBE_PROTOCOL_PREFER == 'ipv4':
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0]
|
||||
else:
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
while True:
|
||||
if packet_queue.full():
|
||||
if packet_queue.get() == 0:
|
||||
lostPacket -= 1
|
||||
@@ -223,7 +214,72 @@ def _net_speed():
|
||||
netSpeed["avgtx"] = avgtx
|
||||
time.sleep(INTERVAL)
|
||||
|
||||
def get_realtime_date():
|
||||
def _disk_io():
|
||||
'''
|
||||
good luck for opensource! by: cpp.la
|
||||
磁盘IO:因为IOPS原因,SSD和HDD、包括RAID卡,ZFS等阵列技术。IO对性能的影响还需要结合自身服务器情况来判断。
|
||||
比如我这里是机械硬盘,大量做随机小文件读写,那么很低的读写也就能造成硬盘长时间的等待。
|
||||
如果这里做连续性IO,那么普通机械硬盘写入到100Mb/s,那么也能造成硬盘长时间的等待。
|
||||
磁盘读写有误差:4k,8k ,https://stackoverflow.com/questions/34413926/psutil-vs-dd-monitoring-disk-i-o
|
||||
:return:
|
||||
'''
|
||||
while True:
|
||||
# pre pid snapshot
|
||||
snapshot_first = {}
|
||||
# next pid snapshot
|
||||
snapshot_second = {}
|
||||
# read count snapshot
|
||||
snapshot_read = 0
|
||||
# write count snapshot
|
||||
snapshot_write = 0
|
||||
# process snapshot
|
||||
pid_snapshot = [str(i) for i in os.listdir("/proc") if i.isdigit() is True]
|
||||
for pid in pid_snapshot:
|
||||
try:
|
||||
with open("/proc/{}/io".format(pid)) as f:
|
||||
pid_io = {}
|
||||
for line in f.readlines():
|
||||
if "read_bytes" in line:
|
||||
pid_io["read"] = int(line.split("read_bytes:")[-1].strip())
|
||||
elif "write_bytes" in line and "cancelled_write_bytes" not in line:
|
||||
pid_io["write"] = int(line.split("write_bytes:")[-1].strip())
|
||||
pid_io["name"] = open("/proc/{}/comm".format(pid), "r").read().strip()
|
||||
snapshot_first[pid] = pid_io
|
||||
except:
|
||||
if pid in snapshot_first:
|
||||
snapshot_first.pop(pid)
|
||||
|
||||
time.sleep(INTERVAL)
|
||||
|
||||
for pid in pid_snapshot:
|
||||
try:
|
||||
with open("/proc/{}/io".format(pid)) as f:
|
||||
pid_io = {}
|
||||
for line in f.readlines():
|
||||
if "read_bytes" in line:
|
||||
pid_io["read"] = int(line.split("read_bytes:")[-1].strip())
|
||||
elif "write_bytes" in line and "cancelled_write_bytes" not in line:
|
||||
pid_io["write"] = int(line.split("write_bytes:")[-1].strip())
|
||||
pid_io["name"] = open("/proc/{}/comm".format(pid), "r").read().strip()
|
||||
snapshot_second[pid] = pid_io
|
||||
except:
|
||||
if pid in snapshot_first:
|
||||
snapshot_first.pop(pid)
|
||||
if pid in snapshot_second:
|
||||
snapshot_second.pop(pid)
|
||||
|
||||
for k, v in snapshot_first.items():
|
||||
if snapshot_first[k]["name"] == snapshot_second[k]["name"] and snapshot_first[k]["name"] != "bash":
|
||||
snapshot_read += (snapshot_second[k]["read"] - snapshot_first[k]["read"])
|
||||
snapshot_write += (snapshot_second[k]["write"] - snapshot_first[k]["write"])
|
||||
diskIO["read"] = snapshot_read
|
||||
diskIO["write"] = snapshot_write
|
||||
|
||||
def get_realtime_data():
|
||||
'''
|
||||
real time get system data
|
||||
:return:
|
||||
'''
|
||||
t1 = threading.Thread(
|
||||
target=_ping_thread,
|
||||
kwargs={
|
||||
@@ -251,14 +307,12 @@ def get_realtime_date():
|
||||
t4 = threading.Thread(
|
||||
target=_net_speed,
|
||||
)
|
||||
t1.setDaemon(True)
|
||||
t2.setDaemon(True)
|
||||
t3.setDaemon(True)
|
||||
t4.setDaemon(True)
|
||||
t1.start()
|
||||
t2.start()
|
||||
t3.start()
|
||||
t4.start()
|
||||
t5 = threading.Thread(
|
||||
target=_disk_io,
|
||||
)
|
||||
for ti in [t1, t2, t3, t4, t5]:
|
||||
ti.daemon = True
|
||||
ti.start()
|
||||
|
||||
def byte_str(object):
|
||||
'''
|
||||
@@ -286,7 +340,7 @@ if __name__ == '__main__':
|
||||
elif 'INTERVAL' in argc:
|
||||
INTERVAL = int(argc.split('INTERVAL=')[-1])
|
||||
socket.setdefaulttimeout(30)
|
||||
get_realtime_date()
|
||||
get_realtime_data()
|
||||
while True:
|
||||
try:
|
||||
print("Connecting...")
|
||||
@@ -324,7 +378,6 @@ if __name__ == '__main__':
|
||||
Load_1, Load_5, Load_15 = os.getloadavg()
|
||||
MemoryTotal, MemoryUsed, SwapTotal, SwapFree = get_memory()
|
||||
HDDTotal, HDDUsed = get_hdd()
|
||||
IP_STATUS = ip_status()
|
||||
|
||||
array = {}
|
||||
if not timer:
|
||||
@@ -348,7 +401,8 @@ if __name__ == '__main__':
|
||||
array['network_tx'] = netSpeed.get("nettx")
|
||||
array['network_in'] = NET_IN
|
||||
array['network_out'] = NET_OUT
|
||||
array['ip_status'] = IP_STATUS
|
||||
# todo:兼容旧版本,下个版本删除ip_status
|
||||
array['ip_status'] = True
|
||||
array['ping_10010'] = lostRate.get('10010') * 100
|
||||
array['ping_189'] = lostRate.get('189') * 100
|
||||
array['ping_10086'] = lostRate.get('10086') * 100
|
||||
@@ -356,6 +410,8 @@ if __name__ == '__main__':
|
||||
array['time_189'] = pingTime.get('189')
|
||||
array['time_10086'] = pingTime.get('10086')
|
||||
array['tcp'], array['udp'], array['process'], array['thread'] = tupd()
|
||||
array['io_read'] = diskIO.get("read")
|
||||
array['io_write'] = diskIO.get("write")
|
||||
|
||||
s.send(byte_str("update " + json.dumps(array) + "\n"))
|
||||
except KeyboardInterrupt:
|
||||
|
||||
@@ -1,35 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
# Update by : https://github.com/cppla/ServerStatus
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20220530
|
||||
# 依赖于psutil跨平台库
|
||||
# 支持Python版本:2.7 to 3.7
|
||||
# 版本:1.0.3, 支持Python版本:2.7 to 3.10
|
||||
# 支持操作系统: Linux, Windows, OSX, Sun Solaris, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
# 时间: 20200407
|
||||
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
|
||||
|
||||
SERVER = "127.0.0.1"
|
||||
USER = "s01"
|
||||
|
||||
|
||||
|
||||
PORT = 35601
|
||||
PASSWORD = "USER_DEFAULT_PASSWORD"
|
||||
INTERVAL = 1
|
||||
PROBEPORT = 80
|
||||
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
|
||||
PING_PACKET_HISTORY_LEN = 100
|
||||
PORT = 35601
|
||||
CU = "cu.tz.cloudcpp.com"
|
||||
CT = "ct.tz.cloudcpp.com"
|
||||
CM = "cm.tz.cloudcpp.com"
|
||||
PROBEPORT = 80
|
||||
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
|
||||
PING_PACKET_HISTORY_LEN = 100
|
||||
INTERVAL = 1
|
||||
|
||||
import socket
|
||||
import time
|
||||
import timeit
|
||||
import os
|
||||
import json
|
||||
import psutil
|
||||
import sys
|
||||
import threading
|
||||
import json
|
||||
import errno
|
||||
import psutil
|
||||
import threading
|
||||
try:
|
||||
from queue import Queue # python3
|
||||
@@ -48,18 +46,22 @@ def get_swap():
|
||||
return int(Mem.total/1024.0), int(Mem.used/1024.0)
|
||||
|
||||
def get_hdd():
|
||||
valid_fs = [ "ext4", "ext3", "ext2", "reiserfs", "jfs", "btrfs", "fuseblk", "zfs", "simfs", "ntfs", "fat32", "exfat", "xfs" ]
|
||||
disks = dict()
|
||||
size = 0
|
||||
used = 0
|
||||
for disk in psutil.disk_partitions():
|
||||
if not disk.device in disks and disk.fstype.lower() in valid_fs:
|
||||
disks[disk.device] = disk.mountpoint
|
||||
for disk in disks.values():
|
||||
usage = psutil.disk_usage(disk)
|
||||
size += usage.total
|
||||
used += usage.used
|
||||
return int(size/1024.0/1024.0), int(used/1024.0/1024.0)
|
||||
if "darwin" in sys.platform:
|
||||
return int(psutil.disk_usage("/").total/1024.0/1024.0), int((psutil.disk_usage("/").total-psutil.disk_usage("/").free)/1024.0/1024.0)
|
||||
else:
|
||||
valid_fs = ["ext4", "ext3", "ext2", "reiserfs", "jfs", "btrfs", "fuseblk", "zfs", "simfs", "ntfs", "fat32",
|
||||
"exfat", "xfs"]
|
||||
disks = dict()
|
||||
size = 0
|
||||
used = 0
|
||||
for disk in psutil.disk_partitions():
|
||||
if not disk.device in disks and disk.fstype.lower() in valid_fs:
|
||||
disks[disk.device] = disk.mountpoint
|
||||
for disk in disks.values():
|
||||
usage = psutil.disk_usage(disk)
|
||||
size += usage.total
|
||||
used += usage.used
|
||||
return int(size/1024.0/1024.0), int(used/1024.0/1024.0)
|
||||
|
||||
def get_cpu():
|
||||
return psutil.cpu_percent(interval=INTERVAL)
|
||||
@@ -90,31 +92,29 @@ def tupd():
|
||||
u = int(os.popen('ss -u|wc -l').read()[:-1])-1
|
||||
p = int(os.popen('ps -ef|wc -l').read()[:-1])-2
|
||||
d = int(os.popen('ps -eLf|wc -l').read()[:-1])-2
|
||||
elif sys.platform.startswith("darwin") is True:
|
||||
t = int(os.popen('lsof -nP -iTCP | wc -l').read()[:-1]) - 1
|
||||
u = int(os.popen('lsof -nP -iUDP | wc -l').read()[:-1]) - 1
|
||||
p = len(psutil.pids())
|
||||
d = 0
|
||||
for k in psutil.pids():
|
||||
try:
|
||||
d += psutil.Process(k).num_threads()
|
||||
except:
|
||||
pass
|
||||
|
||||
elif sys.platform.startswith("win") is True:
|
||||
t = int(os.popen('netstat -an|find "TCP" /c').read()[:-1])-1
|
||||
u = int(os.popen('netstat -an|find "UDP" /c').read()[:-1])-1
|
||||
p = len(psutil.pids())
|
||||
d = 0
|
||||
# cpu is high, default: 0
|
||||
# d = sum([psutil.Process(k).num_threads() for k in [x for x in psutil.pids()]])
|
||||
# if you find cpu is high, please set d=0
|
||||
d = sum([psutil.Process(k).num_threads() for k in psutil.pids()])
|
||||
else:
|
||||
t,u,p,d = 0,0,0,0
|
||||
return t,u,p,d
|
||||
except:
|
||||
return 0,0,0,0
|
||||
|
||||
def ip_status():
|
||||
ip_check = 0
|
||||
for i in [CU, CT, CM]:
|
||||
try:
|
||||
socket.create_connection((i, PROBEPORT), timeout=1).close()
|
||||
except:
|
||||
ip_check += 1
|
||||
if ip_check >= 2:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_network(ip_version):
|
||||
if(ip_version == 4):
|
||||
HOST = "ipv4.google.com"
|
||||
@@ -144,22 +144,27 @@ netSpeed = {
|
||||
'avgrx': 0,
|
||||
'avgtx': 0
|
||||
}
|
||||
diskIO = {
|
||||
'read': 0,
|
||||
'write': 0
|
||||
}
|
||||
|
||||
def _ping_thread(host, mark, port):
|
||||
lostPacket = 0
|
||||
packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN)
|
||||
|
||||
IP = host
|
||||
if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname
|
||||
try:
|
||||
if PROBE_PROTOCOL_PREFER == 'ipv4':
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0]
|
||||
else:
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
|
||||
except Exception:
|
||||
while True:
|
||||
# flush dns, every time.
|
||||
IP = host
|
||||
if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname
|
||||
try:
|
||||
if PROBE_PROTOCOL_PREFER == 'ipv4':
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0]
|
||||
else:
|
||||
IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
while True:
|
||||
if packet_queue.full():
|
||||
if packet_queue.get() == 0:
|
||||
lostPacket -= 1
|
||||
@@ -203,7 +208,67 @@ def _net_speed():
|
||||
netSpeed["avgtx"] = avgtx
|
||||
time.sleep(INTERVAL)
|
||||
|
||||
def get_realtime_date():
|
||||
def _disk_io():
|
||||
"""
|
||||
the code is by: https://github.com/giampaolo/psutil/blob/master/scripts/iotop.py
|
||||
good luck for opensource! modify: cpp.la
|
||||
Calculate IO usage by comparing IO statics before and
|
||||
after the interval.
|
||||
Return a tuple including all currently running processes
|
||||
sorted by IO activity and total disks I/O activity.
|
||||
磁盘IO:因为IOPS原因,SSD和HDD、包括RAID卡,ZFS等。IO对性能的影响还需要结合自身服务器情况来判断。
|
||||
比如我这里是机械硬盘,大量做随机小文件读写,那么很低的读写也就能造成硬盘长时间的等待。
|
||||
如果这里做连续性IO,那么普通机械硬盘写入到100Mb/s,那么也能造成硬盘长时间的等待。
|
||||
磁盘读写有误差:4k,8k ,https://stackoverflow.com/questions/34413926/psutil-vs-dd-monitoring-disk-i-o
|
||||
macos/win,暂不处理。
|
||||
"""
|
||||
if "darwin" in sys.platform or "win" in sys.platform:
|
||||
diskIO["read"] = 0
|
||||
diskIO["write"] = 0
|
||||
else:
|
||||
while True:
|
||||
# first get a list of all processes and disk io counters
|
||||
procs = [p for p in psutil.process_iter()]
|
||||
for p in procs[:]:
|
||||
try:
|
||||
p._before = p.io_counters()
|
||||
except psutil.Error:
|
||||
procs.remove(p)
|
||||
continue
|
||||
disks_before = psutil.disk_io_counters()
|
||||
|
||||
# sleep some time, only when INTERVAL==1 , io read/write per_sec.
|
||||
# when INTERVAL > 1, io read/write per_INTERVAL
|
||||
time.sleep(INTERVAL)
|
||||
|
||||
# then retrieve the same info again
|
||||
for p in procs[:]:
|
||||
with p.oneshot():
|
||||
try:
|
||||
p._after = p.io_counters()
|
||||
p._cmdline = ' '.join(p.cmdline())
|
||||
if not p._cmdline:
|
||||
p._cmdline = p.name()
|
||||
p._username = p.username()
|
||||
except (psutil.NoSuchProcess, psutil.ZombieProcess):
|
||||
procs.remove(p)
|
||||
disks_after = psutil.disk_io_counters()
|
||||
|
||||
# finally calculate results by comparing data before and
|
||||
# after the interval
|
||||
for p in procs:
|
||||
p._read_per_sec = p._after.read_bytes - p._before.read_bytes
|
||||
p._write_per_sec = p._after.write_bytes - p._before.write_bytes
|
||||
p._total = p._read_per_sec + p._write_per_sec
|
||||
|
||||
diskIO["read"] = disks_after.read_bytes - disks_before.read_bytes
|
||||
diskIO["write"] = disks_after.write_bytes - disks_before.write_bytes
|
||||
|
||||
def get_realtime_data():
|
||||
'''
|
||||
real time get system data
|
||||
:return:
|
||||
'''
|
||||
t1 = threading.Thread(
|
||||
target=_ping_thread,
|
||||
kwargs={
|
||||
@@ -231,14 +296,12 @@ def get_realtime_date():
|
||||
t4 = threading.Thread(
|
||||
target=_net_speed,
|
||||
)
|
||||
t1.setDaemon(True)
|
||||
t2.setDaemon(True)
|
||||
t3.setDaemon(True)
|
||||
t4.setDaemon(True)
|
||||
t1.start()
|
||||
t2.start()
|
||||
t3.start()
|
||||
t4.start()
|
||||
t5 = threading.Thread(
|
||||
target=_disk_io,
|
||||
)
|
||||
for ti in [t1, t2, t3, t4, t5]:
|
||||
ti.daemon = True
|
||||
ti.start()
|
||||
|
||||
def byte_str(object):
|
||||
'''
|
||||
@@ -266,7 +329,7 @@ if __name__ == '__main__':
|
||||
elif 'INTERVAL' in argc:
|
||||
INTERVAL = int(argc.split('INTERVAL=')[-1])
|
||||
socket.setdefaulttimeout(30)
|
||||
get_realtime_date()
|
||||
get_realtime_data()
|
||||
while 1:
|
||||
try:
|
||||
print("Connecting...")
|
||||
@@ -301,11 +364,10 @@ if __name__ == '__main__':
|
||||
CPU = get_cpu()
|
||||
NET_IN, NET_OUT = liuliang()
|
||||
Uptime = get_uptime()
|
||||
Load_1, Load_5, Load_15 = os.getloadavg() if 'linux' in sys.platform else (0.0, 0.0, 0.0)
|
||||
Load_1, Load_5, Load_15 = os.getloadavg() if 'linux' in sys.platform or 'darwin' in sys.platform else (0.0, 0.0, 0.0)
|
||||
MemoryTotal, MemoryUsed = get_memory()
|
||||
SwapTotal, SwapUsed = get_swap()
|
||||
HDDTotal, HDDUsed = get_hdd()
|
||||
IP_STATUS = ip_status()
|
||||
|
||||
array = {}
|
||||
if not timer:
|
||||
@@ -329,7 +391,8 @@ if __name__ == '__main__':
|
||||
array['network_tx'] = netSpeed.get("nettx")
|
||||
array['network_in'] = NET_IN
|
||||
array['network_out'] = NET_OUT
|
||||
array['ip_status'] = IP_STATUS
|
||||
# todo:兼容旧版本,下个版本删除ip_status
|
||||
array['ip_status'] = True
|
||||
array['ping_10010'] = lostRate.get('10010') * 100
|
||||
array['ping_189'] = lostRate.get('189') * 100
|
||||
array['ping_10086'] = lostRate.get('10086') * 100
|
||||
@@ -337,6 +400,8 @@ if __name__ == '__main__':
|
||||
array['time_189'] = pingTime.get('189')
|
||||
array['time_10086'] = pingTime.get('10086')
|
||||
array['tcp'], array['udp'], array['process'], array['thread'] = tupd()
|
||||
array['io_read'] = diskIO.get("read")
|
||||
array['io_write'] = diskIO.get("write")
|
||||
|
||||
s.send(byte_str("update " + json.dumps(array) + "\n"))
|
||||
except KeyboardInterrupt:
|
||||
|
||||
25
docker-compose.yml
Normal file
25
docker-compose.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
version: "3"
|
||||
services:
|
||||
serverstatus:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: serverstatus_server
|
||||
container_name: serverstatus
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipv4_address: 172.23.0.2
|
||||
volumes:
|
||||
- ./server/config.json:/ServerStatus/server/config.json
|
||||
- ./web/json:/usr/share/nginx/html/json
|
||||
ports:
|
||||
- 35601:35601
|
||||
- 8080:80
|
||||
|
||||
networks:
|
||||
serverstatus-network:
|
||||
name: serverstatus-network
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.23.0.0/24
|
||||
10
plugin/Dockerfile-telegram
Normal file
10
plugin/Dockerfile-telegram
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM python:alpine
|
||||
|
||||
LABEL maintainer="lidalao"
|
||||
LABEL version="0.0.1"
|
||||
LABEL description="Telegram Bot for ServerStatus"
|
||||
|
||||
WORKDIR /app
|
||||
RUN pip install requests
|
||||
COPY ./bot-telegram.py .
|
||||
CMD [ "python", "./bot-telegram.py" ]
|
||||
73
plugin/bot-telegram.py
Normal file
73
plugin/bot-telegram.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
# Create by : https://github.com/lidalao/ServerStatus
|
||||
# 版本:0.0.1, 支持Python版本:2.7 to 3.9
|
||||
# 支持操作系统: Linux, OSX, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
import time
|
||||
import traceback
|
||||
|
||||
NODE_STATUS_URL = 'http://serverstatus/json/stats.json'
|
||||
|
||||
offs = []
|
||||
counterOff = {}
|
||||
counterOn = {}
|
||||
|
||||
def _send(text):
|
||||
chat_id = os.getenv('TG_CHAT_ID')
|
||||
bot_token = os.environ.get('TG_BOT_TOKEN')
|
||||
url = f"https://api.telegram.org/bot{bot_token}/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=" + chat_id + "&text=" + text
|
||||
try:
|
||||
requests.get(url)
|
||||
except Exception as e:
|
||||
print("catch exception: ", traceback.format_exc())
|
||||
|
||||
def send2tg(srv, flag):
|
||||
if srv not in counterOff:
|
||||
counterOff[srv] = 0
|
||||
if srv not in counterOn:
|
||||
counterOn[srv] = 0
|
||||
|
||||
if flag == 1 : # online
|
||||
if srv in offs:
|
||||
if counterOn[srv] < 10:
|
||||
counterOn[srv] += 1
|
||||
return
|
||||
#1. Remove srv from offs; 2. Send to tg: I am online
|
||||
offs.remove(srv)
|
||||
counterOn[srv] = 0
|
||||
text = '<b>Server Status</b>' + '\n主机上线: ' + srv
|
||||
_send(text)
|
||||
else: #offline
|
||||
if srv not in offs:
|
||||
if counterOff[srv] < 10:
|
||||
counterOff[srv] += 1
|
||||
return
|
||||
#1. Append srv to offs; 2. Send to tg: I am offline
|
||||
offs.append(srv)
|
||||
counterOff[srv] = 0
|
||||
text = '<b>Server Status</b>' + '\n主机下线: ' + srv
|
||||
_send(text)
|
||||
|
||||
def sscmd(address):
|
||||
while True:
|
||||
r = requests.get(url=address, headers={"User-Agent": "ServerStatus/20211116"})
|
||||
try:
|
||||
jsonR = r.json()
|
||||
except Exception as e:
|
||||
print('未发现任何节点')
|
||||
continue
|
||||
for i in jsonR["servers"]:
|
||||
if i["online4"] is False and i["online6"] is False:
|
||||
send2tg(i["name"], 0)
|
||||
else:
|
||||
send2tg(i["name"], 1)
|
||||
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sscmd(NODE_STATUS_URL)
|
||||
38
plugin/docker-compose-telegram.yml
Normal file
38
plugin/docker-compose-telegram.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
version: "3"
|
||||
services:
|
||||
serverstatus:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: Dockerfile
|
||||
image: serverstatus_server
|
||||
container_name: serverstatus
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipv4_address: 172.23.0.2
|
||||
volumes:
|
||||
- ../server/config.json:/ServerStatus/server/config.json
|
||||
- ../web/json:/usr/share/nginx/html/json
|
||||
ports:
|
||||
- 35601:35601
|
||||
- 8080:80
|
||||
bot:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile-telegram
|
||||
image: serverstatus_bot
|
||||
container_name: bot4sss
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
serverstatus-network:
|
||||
ipv4_address: 172.23.0.3
|
||||
environment:
|
||||
- TG_CHAT_ID=${TG_CHAT_ID}
|
||||
- TG_BOT_TOKEN=${TG_BOT_TOKEN}
|
||||
|
||||
networks:
|
||||
serverstatus-network:
|
||||
name: serverstatus-network
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.23.0.0/24
|
||||
@@ -6,7 +6,7 @@ CFLAGS = -Wall -O2
|
||||
|
||||
#CXX = clang++
|
||||
CXX = g++
|
||||
CXXFLAGS = -Wall -O2
|
||||
CXXFLAGS = -Wall -O2 -std=c++11
|
||||
|
||||
ODIR = obj
|
||||
SDIR = src
|
||||
@@ -26,7 +26,7 @@ $(ODIR)/%.o: $(SDIR)/%.cpp
|
||||
$(CXX) -c $(INC) $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(OUT): $(OBJS)
|
||||
$(CXX) $(LIBS) $^ -o $(OUT)
|
||||
$(CXX) $(LIBS) $^ -o $(OUT) -lcurl
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
@@ -1,37 +1,79 @@
|
||||
{"servers":
|
||||
[
|
||||
{
|
||||
"servers": [
|
||||
{
|
||||
"username": "s01",
|
||||
"name": "node1",
|
||||
"type": "xen",
|
||||
"host": "host1",
|
||||
"location": "cn",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
"location": "🇨🇳",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1
|
||||
},
|
||||
{
|
||||
"username": "s02",
|
||||
"name": "node2",
|
||||
"type": "vmware",
|
||||
"host": "host2",
|
||||
"location": "jp",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
"location": "🇯🇵",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1
|
||||
},
|
||||
{
|
||||
"disabled": true,
|
||||
"username": "s03",
|
||||
"name": "node3",
|
||||
"type": "Nothing",
|
||||
"type": "hyper",
|
||||
"host": "host3",
|
||||
"location": "fr",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
"location": "🇫🇷",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1
|
||||
},
|
||||
{
|
||||
"username": "s04",
|
||||
"name": "node4",
|
||||
"type": "kvm",
|
||||
"host": "host4",
|
||||
"location": "kr",
|
||||
"password": "USER_DEFAULT_PASSWORD"
|
||||
"location": "🇰🇷",
|
||||
"password": "USER_DEFAULT_PASSWORD",
|
||||
"monthstart": 1
|
||||
}
|
||||
],
|
||||
"watchdog": [
|
||||
{
|
||||
"name": "cpu high warning",
|
||||
"rule": "cpu>90&load_1>3",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "memory high warning",
|
||||
"rule": "(memory_used/memory_total)*100>90",
|
||||
"interval": 300,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "offline warning",
|
||||
"rule": "online4=0&online6=0",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "ddcc attack",
|
||||
"rule": "tcp_count>500",
|
||||
"interval": 300,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "month traffic warning",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "you can parse an expression combining any known field",
|
||||
"rule": "load_5>3",
|
||||
"interval": 900,
|
||||
"callback": "https://yourSMSurl"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
40746
server/src/exprtk.hpp
Normal file
40746
server/src/exprtk.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,8 @@
|
||||
#include <json.h>
|
||||
#include "server.h"
|
||||
#include "main.h"
|
||||
#include "exprtk.hpp"
|
||||
#include "curl/curl.h"
|
||||
|
||||
#if defined(CONF_FAMILY_UNIX)
|
||||
#include <signal.h>
|
||||
@@ -96,6 +98,13 @@ void CMain::OnDelClient(int ClientNetID)
|
||||
{
|
||||
int ClientID = ClientNetToClient(ClientNetID);
|
||||
dbg_msg("main", "OnDelClient(ncid=%d, cid=%d)", ClientNetID, ClientID);
|
||||
//copy offline message for watchdog
|
||||
WatchdogMessage(ClientNetID,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,0, 0, 0,
|
||||
0, 0, 0, 0);
|
||||
if(ClientID >= 0 && ClientID < NET_MAX_CLIENTS)
|
||||
{
|
||||
Client(ClientID)->m_Connected = false;
|
||||
@@ -178,36 +187,48 @@ int CMain::HandleMessage(int ClientNetID, char *pMessage)
|
||||
pClient->m_Stats.m_HDDTotal = rStart["hdd_total"].u.integer;
|
||||
if(rStart["hdd_used"].type)
|
||||
pClient->m_Stats.m_HDDUsed = rStart["hdd_used"].u.integer;
|
||||
if(rStart["io_read"].type)
|
||||
pClient->m_Stats.m_IORead = rStart["io_read"].u.integer;
|
||||
if(rStart["io_write"].type)
|
||||
pClient->m_Stats.m_IOWrite = rStart["io_write"].u.integer;
|
||||
if(rStart["cpu"].type)
|
||||
pClient->m_Stats.m_CPU = rStart["cpu"].u.dbl;
|
||||
if(rStart["online4"].type && pClient->m_ClientNetType == NETTYPE_IPV6)
|
||||
pClient->m_Stats.m_Online4 = rStart["online4"].u.boolean;
|
||||
if(rStart["online6"].type && pClient->m_ClientNetType == NETTYPE_IPV4)
|
||||
pClient->m_Stats.m_Online6 = rStart["online6"].u.boolean;
|
||||
if(rStart["ip_status"].type)
|
||||
pClient->m_Stats.m_IpStatus = rStart["ip_status"].u.boolean;
|
||||
if(rStart["custom"].type == json_string)
|
||||
str_copy(pClient->m_Stats.m_aCustom, rStart["custom"].u.string.ptr, sizeof(pClient->m_Stats.m_aCustom));
|
||||
|
||||
//copy message for watchdog to analysis
|
||||
WatchdogMessage(ClientNetID,
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15,
|
||||
pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086,
|
||||
pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,
|
||||
pClient->m_Stats.m_tcpCount, pClient->m_Stats.m_udpCount, pClient->m_Stats.m_processCount,
|
||||
pClient->m_Stats.m_threadCount, pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx,
|
||||
pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT,pClient->m_Stats.m_MemTotal,
|
||||
pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed,
|
||||
pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_IORead,
|
||||
pClient->m_Stats.m_IOWrite, pClient->m_Stats.m_CPU, pClient->m_Stats.m_Online4,
|
||||
pClient->m_Stats.m_Online6);
|
||||
|
||||
if(m_Config.m_Verbose)
|
||||
{
|
||||
if(rStart["online4"].type)
|
||||
dbg_msg("main", "Online4: %s\nUptime: %" PRId64 "\nIpStatus: %s\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\n",
|
||||
dbg_msg("main", "Online4: %s\nUptime: %" PRId64 "\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\nIORead: %" PRId64 "\nIOWrite: %" PRId64 "\n",
|
||||
rStart["online4"].u.boolean ? "true" : "false",
|
||||
pClient->m_Stats.m_Uptime,
|
||||
pClient->m_Stats.m_IpStatus ? "true" : "false",
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU);
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU, pClient->m_Stats.m_IORead, pClient->m_Stats.m_IOWrite);
|
||||
else if(rStart["online6"].type)
|
||||
dbg_msg("main", "Online6: %s\nUptime: %" PRId64 "\nIpStatus: %s\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\n",
|
||||
dbg_msg("main", "Online6: %s\nUptime: %" PRId64 "\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\nIORead: %" PRId64 "\nIOWrite: %" PRId64 "\n",
|
||||
rStart["online6"].u.boolean ? "true" : "false",
|
||||
pClient->m_Stats.m_Uptime,
|
||||
pClient->m_Stats.m_IpStatus ? "true" : "false",
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU);
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU, pClient->m_Stats.m_IORead, pClient->m_Stats.m_IOWrite);
|
||||
else
|
||||
dbg_msg("main", "Uptime: %" PRId64 "\nIpStatus: %s\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\n",
|
||||
dbg_msg("main", "Uptime: %" PRId64 "\nLoad_1: %f\nLoad_5: %f\nLoad_15: %f\nPing_10010: %f\nPing_189: %f\nPing_10086: %f\nTime_10010: %" PRId64 "\nTime_189: %" PRId64 "\nTime_10086: %" PRId64 "\nTcp_count: %" PRId64 "\nUdp_count: %" PRId64 "\nprocess_count: %" PRId64 "\nthread_count: %" PRId64 "\nNetworkRx: %" PRId64 "\nNetworkTx: %" PRId64 "\nNetworkIN: %" PRId64 "\nNetworkOUT: %" PRId64 "\nMemTotal: %" PRId64 "\nMemUsed: %" PRId64 "\nSwapTotal: %" PRId64 "\nSwapUsed: %" PRId64 "\nHDDTotal: %" PRId64 "\nHDDUsed: %" PRId64 "\nCPU: %f\nIORead: %" PRId64 "\nIOWrite: %" PRId64 "\n",
|
||||
pClient->m_Stats.m_Uptime,
|
||||
pClient->m_Stats.m_IpStatus ? "true" : "false",
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU);
|
||||
pClient->m_Stats.m_Load_1, pClient->m_Stats.m_Load_5, pClient->m_Stats.m_Load_15, pClient->m_Stats.m_ping_10010, pClient->m_Stats.m_ping_189, pClient->m_Stats.m_ping_10086, pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,pClient->m_Stats.m_tcpCount,pClient->m_Stats.m_udpCount,pClient->m_Stats.m_processCount,pClient->m_Stats.m_threadCount,pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx, pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT, pClient->m_Stats.m_MemTotal, pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed, pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_CPU, pClient->m_Stats.m_IORead, pClient->m_Stats.m_IOWrite);
|
||||
}
|
||||
|
||||
// clean up
|
||||
@@ -235,6 +256,113 @@ int CMain::HandleMessage(int ClientNetID, char *pMessage)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, double load_15, double ping_10010, double ping_189, double ping_10086,
|
||||
double time_10010, double time_189, double time_10086, double tcp_count, double udp_count, double process_count, double thread_count,
|
||||
double network_rx, double network_tx, double network_in, double network_out, double memory_total, double memory_used,
|
||||
double swap_total, double swap_used, double hdd_total, double hdd_used, double io_read, double io_write, double cpu,
|
||||
double online4, double online6)
|
||||
{
|
||||
int ID = 0;
|
||||
while (strcmp(Watchdog(ID)->m_aName, "NULL"))
|
||||
{
|
||||
typedef exprtk::symbol_table<double> symbol_table_t;
|
||||
typedef exprtk::expression<double> expression_t;
|
||||
typedef exprtk::parser<double> parser_t;
|
||||
const std::string expression_string = Watchdog(ID)->m_aRule;
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable("load_1",load_1);
|
||||
symbol_table.add_variable("load_5",load_5);
|
||||
symbol_table.add_variable("load_15",load_15);
|
||||
symbol_table.add_variable("ping_10010",ping_10010);
|
||||
symbol_table.add_variable("ping_189",ping_189);
|
||||
symbol_table.add_variable("ping_10086",ping_10086);
|
||||
symbol_table.add_variable("time_10010",time_10010);
|
||||
symbol_table.add_variable("time_189",time_189);
|
||||
symbol_table.add_variable("time_10086",time_10086);
|
||||
symbol_table.add_variable("tcp_count",tcp_count);
|
||||
symbol_table.add_variable("udp_count",udp_count);
|
||||
symbol_table.add_variable("process_count",process_count);
|
||||
symbol_table.add_variable("thread_count",thread_count);
|
||||
symbol_table.add_variable("network_rx",network_rx);
|
||||
symbol_table.add_variable("network_tx",network_tx);
|
||||
symbol_table.add_variable("network_in",network_in);
|
||||
symbol_table.add_variable("network_out",network_out);
|
||||
symbol_table.add_variable("memory_total",memory_total);
|
||||
symbol_table.add_variable("memory_used",memory_used);
|
||||
symbol_table.add_variable("swap_total",swap_total);
|
||||
symbol_table.add_variable("swap_used",swap_used);
|
||||
symbol_table.add_variable("hdd_total",hdd_total);
|
||||
symbol_table.add_variable("hdd_used",hdd_used);
|
||||
symbol_table.add_variable("io_read",io_read);
|
||||
symbol_table.add_variable("io_write",io_write);
|
||||
symbol_table.add_variable("cpu",cpu);
|
||||
symbol_table.add_variable("online4",online4);
|
||||
symbol_table.add_variable("online6",online6);
|
||||
symbol_table.add_constants();
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_string,expression);
|
||||
|
||||
if (expression.value() > 0)
|
||||
{
|
||||
int ClientID = ClientNetToClient(ClientNetID);
|
||||
time_t currentStamp = (long long)time(/*ago*/0);
|
||||
if ((currentStamp-Client(ClientID)->m_AlarmLastTime) > Watchdog(ID)->m_aInterval)
|
||||
{
|
||||
Client(ClientID)->m_AlarmLastTime = currentStamp;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
//standard time
|
||||
char standardTime[32]= { 0 };
|
||||
strftime(standardTime, sizeof(standardTime), "%Y-%m-%d %H:%M:%S",localtime(¤tStamp));
|
||||
|
||||
//url encode, Rules conflict with url special characters,eg:&, del rules, by https://cpp.la, 2023-10-09
|
||||
char encodeBuffer[2048] = { 0 };
|
||||
sprintf(encodeBuffer, "【告警名称】 %s \n\n【告警时间】 %s \n\n【用户名】 %s \n\n【节点名】 %s \n\n【虚拟化】 %s \n\n【主机名】 %s \n\n【位 置】 %s",
|
||||
Watchdog(ID)->m_aName,
|
||||
standardTime,
|
||||
Client(ClientID)->m_aUsername,
|
||||
Client(ClientID)->m_aName,
|
||||
Client(ClientID)->m_aType,
|
||||
Client(ClientID)->m_aHost,
|
||||
Client(ClientID)->m_aLocation);
|
||||
char *encodeUrl = curl_easy_escape(curl, encodeBuffer, strlen(encodeBuffer));
|
||||
|
||||
//standard url
|
||||
char urlBuffer[2048] = { 0 };
|
||||
sprintf(urlBuffer, "%s%s",Watchdog(ID)->m_aCallback, encodeUrl);
|
||||
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, urlBuffer);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,"signature=ServerStatus");
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 6L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "watchdog failed: %s\n", curl_easy_strerror(res));
|
||||
if(encodeUrl)
|
||||
curl_free(encodeUrl);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
|
||||
void CMain::JSONUpdateThread(void *pUser)
|
||||
{
|
||||
CJSONUpdateThreadData *m_pJSONUpdateThreadData = (CJSONUpdateThreadData *)pUser;
|
||||
@@ -269,17 +397,35 @@ void CMain::JSONUpdateThread(void *pUser)
|
||||
else
|
||||
str_format(aUptime, sizeof(aUptime), "%02d:%02d:%02d", (int)(pClients[i].m_Stats.m_Uptime/60.0/60.0), (int)((pClients[i].m_Stats.m_Uptime/60)%60), (int)((pClients[i].m_Stats.m_Uptime)%60));
|
||||
|
||||
// track month network traffic, diff: 2021-10-01 00:05, 5minutes
|
||||
// last_network_in/out is last record flag.
|
||||
time_t currentStamp = (long long)time(/*ago*/0);
|
||||
if(0 == pClients[i].m_LastNetworkIN || (0 != pClients[i].m_Stats.m_NetworkIN && pClients[i].m_LastNetworkIN > pClients[i].m_Stats.m_NetworkIN) || (localtime(¤tStamp)->tm_mday == pClients[i].m_aMonthStart && localtime(¤tStamp)->tm_hour == 0 && localtime(¤tStamp)->tm_min < 5))
|
||||
{
|
||||
pClients[i].m_LastNetworkIN = pClients[i].m_Stats.m_NetworkIN;
|
||||
pClients[i].m_LastNetworkOUT = pClients[i].m_Stats.m_NetworkOUT;
|
||||
}
|
||||
|
||||
str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf),
|
||||
"{ \"name\": \"%s\",\"type\": \"%s\",\"host\": \"%s\",\"location\": \"%s\",\"online4\": %s, \"online6\": %s,\"ip_status\": %s,\"uptime\": \"%s\",\"load_1\": %.2f, \"load_5\": %.2f, \"load_15\": %.2f,\"ping_10010\": %.2f, \"ping_189\": %.2f, \"ping_10086\": %.2f,\"time_10010\": %" PRId64 ", \"time_189\": %" PRId64 ", \"time_10086\": %" PRId64 ", \"tcp_count\": %" PRId64 ", \"udp_count\": %" PRId64 ", \"process_count\": %" PRId64 ", \"thread_count\": %" PRId64 ", \"network_rx\": %" PRId64 ", \"network_tx\": %" PRId64 ", \"network_in\": %" PRId64 ", \"network_out\": %" PRId64 ", \"cpu\": %d, \"memory_total\": %" PRId64 ", \"memory_used\": %" PRId64 ", \"swap_total\": %" PRId64 ", \"swap_used\": %" PRId64 ", \"hdd_total\": %" PRId64 ", \"hdd_used\": %" PRId64 ", \"custom\": \"%s\" },\n",
|
||||
"{ \"name\": \"%s\",\"type\": \"%s\",\"host\": \"%s\",\"location\": \"%s\",\"online4\": %s, \"online6\": %s, \"uptime\": \"%s\",\"load_1\": %.2f, \"load_5\": %.2f, \"load_15\": %.2f,\"ping_10010\": %.2f, \"ping_189\": %.2f, \"ping_10086\": %.2f,\"time_10010\": %" PRId64 ", \"time_189\": %" PRId64 ", \"time_10086\": %" PRId64 ", \"tcp_count\": %" PRId64 ", \"udp_count\": %" PRId64 ", \"process_count\": %" PRId64 ", \"thread_count\": %" PRId64 ", \"network_rx\": %" PRId64 ", \"network_tx\": %" PRId64 ", \"network_in\": %" PRId64 ", \"network_out\": %" PRId64 ", \"cpu\": %d, \"memory_total\": %" PRId64 ", \"memory_used\": %" PRId64 ", \"swap_total\": %" PRId64 ", \"swap_used\": %" PRId64 ", \"hdd_total\": %" PRId64 ", \"hdd_used\": %" PRId64 ", \"last_network_in\": %" PRId64 ", \"last_network_out\": %" PRId64 ",\"io_read\": %" PRId64 ", \"io_write\": %" PRId64 ",\"custom\": \"%s\" },\n",
|
||||
pClients[i].m_aName,pClients[i].m_aType,pClients[i].m_aHost,pClients[i].m_aLocation,
|
||||
pClients[i].m_Stats.m_Online4 ? "true" : "false",pClients[i].m_Stats.m_Online6 ? "true" : "false",pClients[i].m_Stats.m_IpStatus ? "true": "false",
|
||||
aUptime, pClients[i].m_Stats.m_Load_1, pClients[i].m_Stats.m_Load_5, pClients[i].m_Stats.m_Load_15, pClients[i].m_Stats.m_ping_10010, pClients[i].m_Stats.m_ping_189, pClients[i].m_Stats.m_ping_10086, pClients[i].m_Stats.m_time_10010, pClients[i].m_Stats.m_time_189, pClients[i].m_Stats.m_time_10086,pClients[i].m_Stats.m_tcpCount,pClients[i].m_Stats.m_udpCount,pClients[i].m_Stats.m_processCount,pClients[i].m_Stats.m_threadCount,pClients[i].m_Stats.m_NetworkRx, pClients[i].m_Stats.m_NetworkTx, pClients[i].m_Stats.m_NetworkIN, pClients[i].m_Stats.m_NetworkOUT, (int)pClients[i].m_Stats.m_CPU, pClients[i].m_Stats.m_MemTotal, pClients[i].m_Stats.m_MemUsed, pClients[i].m_Stats.m_SwapTotal, pClients[i].m_Stats.m_SwapUsed, pClients[i].m_Stats.m_HDDTotal, pClients[i].m_Stats.m_HDDUsed, pClients[i].m_Stats.m_aCustom);
|
||||
pClients[i].m_Stats.m_Online4 ? "true" : "false",pClients[i].m_Stats.m_Online6 ? "true" : "false",
|
||||
aUptime, pClients[i].m_Stats.m_Load_1, pClients[i].m_Stats.m_Load_5, pClients[i].m_Stats.m_Load_15, pClients[i].m_Stats.m_ping_10010, pClients[i].m_Stats.m_ping_189, pClients[i].m_Stats.m_ping_10086,
|
||||
pClients[i].m_Stats.m_time_10010, pClients[i].m_Stats.m_time_189, pClients[i].m_Stats.m_time_10086,pClients[i].m_Stats.m_tcpCount,pClients[i].m_Stats.m_udpCount,pClients[i].m_Stats.m_processCount,pClients[i].m_Stats.m_threadCount,
|
||||
pClients[i].m_Stats.m_NetworkRx, pClients[i].m_Stats.m_NetworkTx, pClients[i].m_Stats.m_NetworkIN, pClients[i].m_Stats.m_NetworkOUT, (int)pClients[i].m_Stats.m_CPU, pClients[i].m_Stats.m_MemTotal, pClients[i].m_Stats.m_MemUsed,
|
||||
pClients[i].m_Stats.m_SwapTotal, pClients[i].m_Stats.m_SwapUsed, pClients[i].m_Stats.m_HDDTotal, pClients[i].m_Stats.m_HDDUsed,
|
||||
pClients[i].m_Stats.m_NetworkIN == 0 || pClients[i].m_LastNetworkIN == 0 ? pClients[i].m_Stats.m_NetworkIN : pClients[i].m_LastNetworkIN,
|
||||
pClients[i].m_Stats.m_NetworkOUT == 0 || pClients[i].m_LastNetworkOUT == 0 ? pClients[i].m_Stats.m_NetworkOUT : pClients[i].m_LastNetworkOUT,
|
||||
pClients[i].m_Stats.m_IORead, pClients[i].m_Stats.m_IOWrite,
|
||||
pClients[i].m_Stats.m_aCustom);
|
||||
pBuf += strlen(pBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf), "{ \"name\": \"%s\", \"type\": \"%s\", \"host\": \"%s\", \"location\": \"%s\", \"online4\": false, \"online6\": false },\n",
|
||||
pClients[i].m_aName, pClients[i].m_aType, pClients[i].m_aHost, pClients[i].m_aLocation);
|
||||
// sava network traffic record to json when close client
|
||||
// last_network_in == last network in record, last_network_out == last network out record
|
||||
str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf), "{ \"name\": \"%s\", \"type\": \"%s\", \"host\": \"%s\", \"location\": \"%s\", \"online4\": false, \"online6\": false, \"last_network_in\": %" PRId64 ", \"last_network_out\": %" PRId64 " },\n",
|
||||
pClients[i].m_aName, pClients[i].m_aType, pClients[i].m_aHost, pClients[i].m_aLocation, pClients[i].m_LastNetworkIN, pClients[i].m_LastNetworkOUT);
|
||||
pBuf += strlen(pBuf);
|
||||
}
|
||||
}
|
||||
@@ -306,7 +452,11 @@ void CMain::JSONUpdateThread(void *pUser)
|
||||
fs_rename(aJSONFileTmp, pConfig->m_aJSONFile);
|
||||
thread_sleep(1000);
|
||||
}
|
||||
fs_remove(pConfig->m_aJSONFile);
|
||||
// support by: https://cpp.la. don't remove month traffic record, storage as "stats.json~", remark: 2021-10-18
|
||||
// fs_remove(pConfig->m_aJSONFile);
|
||||
char aJSONFileTmp[1024];
|
||||
str_format(aJSONFileTmp, sizeof(aJSONFileTmp), "%s~", pConfig->m_aJSONFile);
|
||||
fs_rename(pConfig->m_aJSONFile, aJSONFileTmp);
|
||||
}
|
||||
|
||||
int CMain::ReadConfig()
|
||||
@@ -367,21 +517,102 @@ int CMain::ReadConfig()
|
||||
str_copy(Client(ID)->m_aHost, rStart[i]["host"].u.string.ptr, sizeof(Client(ID)->m_aHost));
|
||||
str_copy(Client(ID)->m_aLocation, rStart[i]["location"].u.string.ptr, sizeof(Client(ID)->m_aLocation));
|
||||
str_copy(Client(ID)->m_aPassword, rStart[i]["password"].u.string.ptr, sizeof(Client(ID)->m_aPassword));
|
||||
//if month start day > 28, diff: 3days(29,30,31)
|
||||
Client(ID)->m_aMonthStart = rStart[i]["monthstart"].u.integer;
|
||||
if(Client(ID)->m_aMonthStart > 28)
|
||||
{
|
||||
Client(ID)->m_aMonthStart = 28;
|
||||
}
|
||||
Client(ID)->m_LastNetworkIN = 0;
|
||||
Client(ID)->m_LastNetworkOUT = 0;
|
||||
|
||||
if(m_Config.m_Verbose)
|
||||
{
|
||||
if(Client(ID)->m_Disabled)
|
||||
dbg_msg("main", "[#%d: Name: \"%s\", Username: \"%s\", Type: \"%s\", Host: \"%s\", Location: \"%s\", Password: \"%s\"]",
|
||||
ID, Client(ID)->m_aName, Client(ID)->m_aUsername, Client(ID)->m_aType, Client(ID)->m_aHost, Client(ID)->m_aLocation, Client(ID)->m_aPassword);
|
||||
dbg_msg("main", "[#%d: Name: \"%s\", Username: \"%s\", Type: \"%s\", Host: \"%s\", Location: \"%s\", Password: \"%s\", MonthStart: %\" PRId64 \"]",
|
||||
ID, Client(ID)->m_aName, Client(ID)->m_aUsername, Client(ID)->m_aType, Client(ID)->m_aHost, Client(ID)->m_aLocation, Client(ID)->m_aPassword, Client(ID)->m_aMonthStart);
|
||||
else
|
||||
dbg_msg("main", "#%d: Name: \"%s\", Username: \"%s\", Type: \"%s\", Host: \"%s\", Location: \"%s\", Password: \"%s\"",
|
||||
ID, Client(ID)->m_aName, Client(ID)->m_aUsername, Client(ID)->m_aType, Client(ID)->m_aHost, Client(ID)->m_aLocation, Client(ID)->m_aPassword);
|
||||
dbg_msg("main", "#%d: Name: \"%s\", Username: \"%s\", Type: \"%s\", Host: \"%s\", Location: \"%s\", Password: \"%s\", MonthStart: %\" PRId64 \"",
|
||||
ID, Client(ID)->m_aName, Client(ID)->m_aUsername, Client(ID)->m_aType, Client(ID)->m_aHost, Client(ID)->m_aLocation, Client(ID)->m_aPassword, Client(ID)->m_aMonthStart);
|
||||
|
||||
}
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
|
||||
// watch dog
|
||||
// support by: https://cpp.la
|
||||
ID = 0;
|
||||
const json_value &jStart = (*pJsonData)["watchdog"];
|
||||
if(jStart.type == json_array)
|
||||
{
|
||||
for(unsigned i = 0; i < jStart.u.array.length; i++)
|
||||
{
|
||||
if(ID < 0 || ID >= NET_MAX_CLIENTS)
|
||||
continue;
|
||||
|
||||
str_copy(Watchdog(ID)->m_aName, jStart[i]["name"].u.string.ptr, sizeof(Watchdog(ID)->m_aName));
|
||||
str_copy(Watchdog(ID)->m_aRule, jStart[i]["rule"].u.string.ptr, sizeof(Watchdog(ID)->m_aRule));
|
||||
Watchdog(ID)->m_aInterval = jStart[i]["interval"].u.integer;
|
||||
str_copy(Watchdog(ID)->m_aCallback, jStart[i]["callback"].u.string.ptr, sizeof(Watchdog(ID)->m_aCallback));
|
||||
|
||||
ID++;
|
||||
}
|
||||
str_copy(Watchdog(ID)->m_aName, "NULL", sizeof(Watchdog(ID)->m_aName));
|
||||
} else
|
||||
str_copy(Watchdog(ID)->m_aName, "NULL", sizeof(Watchdog(ID)->m_aName));
|
||||
|
||||
// if file exists, read last network traffic record,reset m_LastNetworkIN and m_LastNetworkOUT
|
||||
// support by: https://cpp.la
|
||||
IOHANDLE nFile = io_open(m_Config.m_aJSONFile, IOFLAG_READ);
|
||||
if(!nFile)
|
||||
{
|
||||
char aJSONFileTmp[1024];
|
||||
str_format(aJSONFileTmp, sizeof(aJSONFileTmp), "%s~", m_Config.m_aJSONFile);
|
||||
nFile = io_open(aJSONFileTmp, IOFLAG_READ);
|
||||
}
|
||||
if(nFile)
|
||||
{
|
||||
int nFileSize = (int)io_length(nFile);
|
||||
char *pNFileData = (char *)mem_alloc(nFileSize + 1, 1);
|
||||
|
||||
io_read(nFile, pNFileData, nFileSize);
|
||||
pNFileData[nFileSize] = 0;
|
||||
io_close(nFile);
|
||||
|
||||
json_settings nJsonSettings;
|
||||
mem_zero(&nJsonSettings, sizeof(nJsonSettings));
|
||||
json_value *pNJsonData = json_parse_ex(&nJsonSettings, pNFileData, strlen(pNFileData), aError);
|
||||
if(pNJsonData)
|
||||
{
|
||||
const json_value &cStart = (*pNJsonData)["servers"];
|
||||
if(rStart.type == json_array)
|
||||
{
|
||||
int ID = 0;
|
||||
for(unsigned i = 0; i < rStart.u.array.length; i++)
|
||||
{
|
||||
if(ID < 0 || ID >= NET_MAX_CLIENTS)
|
||||
continue;
|
||||
for(unsigned j = 0; j < cStart.u.array.length; j++)
|
||||
{
|
||||
if(strcmp(Client(ID)->m_aName, cStart[j]["name"].u.string.ptr)==0 &&
|
||||
strcmp(Client(ID)->m_aType, cStart[j]["type"].u.string.ptr)==0 &&
|
||||
strcmp(Client(ID)->m_aHost, cStart[j]["host"].u.string.ptr)==0 &&
|
||||
strcmp(Client(ID)->m_aLocation, cStart[j]["location"].u.string.ptr)==0)
|
||||
{
|
||||
Client(ID)->m_LastNetworkIN = cStart[j]["last_network_in"].u.integer;
|
||||
Client(ID)->m_LastNetworkOUT = cStart[j]["last_network_out"].u.integer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
json_value_free(pNJsonData);
|
||||
}
|
||||
mem_free(pNFileData);
|
||||
}
|
||||
|
||||
// clean up
|
||||
json_value_free(pJsonData);
|
||||
mem_free(pFileData);
|
||||
@@ -486,3 +717,4 @@ int main(int argc, const char *argv[])
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,15 +36,20 @@ class CMain
|
||||
char m_aHost[128];
|
||||
char m_aLocation[128];
|
||||
char m_aPassword[128];
|
||||
int m_aMonthStart; //track month network traffic. by: https://cpp.la
|
||||
|
||||
int64 m_TimeConnected;
|
||||
int64 m_LastUpdate;
|
||||
int64_t m_LastNetworkIN; //restore month traffic info.
|
||||
int64_t m_LastNetworkOUT; //restore month traffic info.
|
||||
int64_t m_TimeConnected;
|
||||
int64_t m_LastUpdate;
|
||||
int64_t m_AlarmLastTime; //record last alarm time.
|
||||
|
||||
struct CStats
|
||||
{
|
||||
bool m_Online4;
|
||||
bool m_Online6;
|
||||
bool m_IpStatus; //mh361 or mh370, mourn mh370, 2014-03-08 01:20 lost from all over the world. by:cpp.la
|
||||
// bool m_IpStatus, delete ip_status check, Duplicate packet loss rate detection
|
||||
// mh361 or mh370, mourn mh370, 2014-03-08 01:20 lost from all over the world. by:https://cpp.la
|
||||
int64_t m_Uptime;
|
||||
double m_Load_1;
|
||||
double m_Load_5;
|
||||
@@ -69,6 +74,8 @@ class CMain
|
||||
int64_t m_udpCount;
|
||||
int64_t m_processCount;
|
||||
int64_t m_threadCount;
|
||||
int64_t m_IORead;
|
||||
int64_t m_IOWrite;
|
||||
double m_CPU;
|
||||
char m_aCustom[512];
|
||||
// Options
|
||||
@@ -76,6 +83,13 @@ class CMain
|
||||
} m_Stats;
|
||||
} m_aClients[NET_MAX_CLIENTS];
|
||||
|
||||
struct CWatchDog{
|
||||
char m_aName[128];
|
||||
char m_aRule[128];
|
||||
int m_aInterval;
|
||||
char m_aCallback[1024];
|
||||
} m_aCWatchDogs[NET_MAX_CLIENTS];
|
||||
|
||||
struct CJSONUpdateThreadData
|
||||
{
|
||||
CClient *pClients;
|
||||
@@ -93,6 +107,14 @@ public:
|
||||
int ReadConfig();
|
||||
int Run();
|
||||
|
||||
CWatchDog *Watchdog(int ruleID) { return &m_aCWatchDogs[ruleID]; }
|
||||
void WatchdogMessage(int ClientNetID,
|
||||
double load_1, double load_5, double load_15, double ping_10010, double ping_189, double ping_10086,
|
||||
double time_10010, double time_189, double time_10086, double tcp_count, double udp_count, double process_count, double thread_count,
|
||||
double network_rx, double network_tx, double network_in, double network_out,double memory_total,
|
||||
double memory_used,double swap_total, double swap_used, double hdd_total,
|
||||
double hdd_used, double io_read, double io_write, double cpu,double online4, double online6);
|
||||
|
||||
CClient *Client(int ClientID) { return &m_aClients[ClientID]; }
|
||||
CClient *ClientNet(int ClientNetID);
|
||||
const CConfig *Config() const { return &m_Config; }
|
||||
|
||||
@@ -10,7 +10,7 @@ enum
|
||||
NET_CONNSTATE_ERROR=4,
|
||||
|
||||
NET_MAX_PACKETSIZE = 1400,
|
||||
NET_MAX_CLIENTS = 128
|
||||
NET_MAX_CLIENTS = 256
|
||||
};
|
||||
|
||||
typedef int (*NETFUNC_DELCLIENT)(int ClientID, const char* pReason, void *pUser);
|
||||
|
||||
9
service/status-client.service
Normal file
9
service/status-client.service
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=ServerStatus-Client
|
||||
After=network.target
|
||||
[Service]
|
||||
ExecStart=/usr/bin/python3 /usr/local/ServerStatus/clients/client-linux.py
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
9
service/status-server.service
Normal file
9
service/status-server.service
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=ServerStatus-Server
|
||||
After=network.target
|
||||
[Service]
|
||||
ExecStart=/usr/local/ServerStatus/server/sergate --config=/usr/local/ServerStatus/server/config.json --web-dir=/usr/local/ServerStatus/web
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
1
web/css/bootstrap-theme.min.css.map
Normal file
1
web/css/bootstrap-theme.min.css.map
Normal file
File diff suppressed because one or more lines are too long
2
web/css/bootstrap.min.css
vendored
2
web/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
1
web/css/bootstrap.min.css.map
Normal file
1
web/css/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
@@ -1,54 +1,71 @@
|
||||
body { background: #222 url('../img/dark.png'); color: #fff; }
|
||||
body { background: #212e36 url('../img/dark.png'); color: #dcdcdc; }
|
||||
.navbar { min-height: 40px; }
|
||||
.navbar-brand { color: #FFF !important; padding: 10px; font-size: 20px; }
|
||||
.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
|
||||
.dropdown-menu > li > a { color: #FFF !important; background-color: #222222 !important; }
|
||||
.dropdown-menu > li > a:hover { color: #FFF !important; background: #000 !important; }
|
||||
.dropdown-menu { background: #222 !important; background-color: #222222 !important; }
|
||||
.navbar-inverse .navbar-inner { background-color:#1B1B1B; background-image:-moz-linear-gradient(top, #222222, #111111); background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); background-image:-webkit-linear-gradient(top, #222222, #111111); background-image:-o-linear-gradient(top, #222222, #111111); background-image:linear-gradient(to bottom, #222222, #111111); background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); border-color: #252525; }
|
||||
.content { background: #222; padding: 20px; border-radius: 5px; border: 1px #000 solid; -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); box-shadow: 0 1px 10px rgba(0, 0, 0, .1); margin-bottom: 20px; }
|
||||
.table { background: #000; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
|
||||
.navbar-inverse .navbar-inner { background-color:#1B1B1B; background-image:-moz-linear-gradient(top, #222222, #111111); background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); background-image:-webkit-linear-gradient(top, #222222, #111111); background-image:-o-linear-gradient(top, #222222, #111111); background-image:linear-gradient(to bottom, #212e36, #212e36); background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); border-color: #252525; }
|
||||
.container { width: 1280px; }
|
||||
.content { background: #212e36; padding: 20px; border-radius: 5px; border: 1px #212e36 solid; -webkit-box-shadow: 0 0px 0px rgba(0, 0, 0, 0); -moz-box-shadow: 0 0px 0px rgba(0, 0, 0, 0); box-shadow: 0 0px 0px rgba(0, 0, 0, 0); margin-bottom: 20px; }
|
||||
.table { background: #363b40; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
|
||||
.table th { text-align: center; }
|
||||
.table-striped tbody > tr.even > td, .table-striped tbody > tr.even > th { background-color: #2F2F2F; }
|
||||
.table-striped tbody > tr.odd > td, .table-striped tbody > tr.odd > th { background-color: #000; }
|
||||
.table-striped tbody > tr.even > td, .table-striped tbody > tr.even > th { background-color: #212e36; }
|
||||
.table-striped tbody > tr.odd > td, .table-striped tbody > tr.odd > th { background-color: #212e36; }
|
||||
.table td { text-align: center; border-color: #2F2F2F; }
|
||||
.progress { margin-bottom: 0; background: #222; }
|
||||
.progress { margin-bottom: 0; background: #363b40; }
|
||||
.table-hover > tbody > tr:hover > td { background: #414141; }
|
||||
tr.even.expandRow > :hover { background: #2F2F2F !important; }
|
||||
tr.odd.expandRow > :hover { background: #000 !important; }
|
||||
tr.even.expandRow > :hover { background: #212e36 !important; }
|
||||
tr.odd.expandRow > :hover { background: #212e36 !important; }
|
||||
.expandRow > td { padding: 0 !important; border-top: 0px !important; }
|
||||
#cpu, #ram, #hdd, #network { min-width: 55px; max-width: 100px; }
|
||||
#ping { min-width: 55px; max-width: 130px; }
|
||||
#month_traffic { min-width: 85px; max-width: 95px;}
|
||||
#network { min-width: 110px; }
|
||||
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
|
||||
#ping { max-width: 110px; }
|
||||
|
||||
@media only screen and (max-width: 992px) {
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 720px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
@media only screen and (max-width: 620px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 533px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#network, tr td:nth-child(8) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 450px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#network, tr td:nth-child(8) { display:none; visibility:hidden; }
|
||||
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ body { background: #ebebeb url('../img/light.png'); }
|
||||
.navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
|
||||
.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
|
||||
.navbar-inverse .navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
|
||||
.container { width: 1280px; }
|
||||
.content { background: #ffffff; padding: 20px; border-radius: 5px; border: 1px #cecece solid; -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); box-shadow: 0 1px 10px rgba(0, 0, 0, .1); margin-bottom: 20px; }
|
||||
.table { background: #ffffff; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
|
||||
.table th, .table td { text-align: center; }
|
||||
@@ -14,38 +15,54 @@ body { background: #ebebeb url('../img/light.png'); }
|
||||
tr.even.expandRow > :hover { background: #F9F9F9 !important; }
|
||||
tr.odd.expandRow > :hover { background: #FFF !important; }
|
||||
.expandRow > td { padding: 0 !important; border-top: 0px !important; }
|
||||
#cpu, #ram, #hdd, #network { min-width: 55px; max-width: 100px; }
|
||||
#ping { min-width: 55px; max-width: 130px; }
|
||||
#month_traffic { min-width: 85px; max-width: 95px;}
|
||||
#network { min-width: 110px; }
|
||||
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
|
||||
#ping { max-width: 110px; }
|
||||
|
||||
@media only screen and (max-width: 992px) {
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 720px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
@media only screen and (max-width: 620px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 533px) {
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#network, tr td:nth-child(8) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
@media only screen and (max-width: 450px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#network, tr td:nth-child(8) { display:none; visibility:hidden; }
|
||||
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
|
||||
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
||||
#type, tr td:nth-child(4) { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
|
||||
BIN
web/img/dark.png
BIN
web/img/dark.png
Binary file not shown.
|
Before Width: | Height: | Size: 600 B After Width: | Height: | Size: 1.9 KiB |
@@ -1,13 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
json字段保持完整, 后期更新会向下兼容
|
||||
可以自定义前端展示
|
||||
json字段保持完整, 自行自定义前端展示
|
||||
ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)
|
||||
by:https://www.cpp.la
|
||||
follow me, better solution for you. by:https://cpp.la
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
@@ -19,8 +18,8 @@
|
||||
<meta name="author" content="BotoX">
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/bootstrap-theme.min.css">
|
||||
<link rel="stylesheet" href="css/dark.css" title="dark">
|
||||
<link rel="stylesheet" href="css/light.css" title="light">
|
||||
<link rel="stylesheet" href="css/dark.css" title="dark">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 70px;
|
||||
@@ -51,8 +50,8 @@
|
||||
<li class="dropdown">
|
||||
<a data-toggle="dropdown" class="dropdown-toggle" href="#">风格<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" onclick="setActiveStyleSheet('dark')">黑夜</a></li>
|
||||
<li><a href="#" onclick="setActiveStyleSheet('light')">白天</a></li>
|
||||
<li><a href="#" onclick="setActiveStyleSheet('dark', true)">黑夜</a></li>
|
||||
<li><a href="#" onclick="setActiveStyleSheet('light', true)">白天</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -76,19 +75,19 @@
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="status4" style="text-align: center;">协议</th>
|
||||
<th id="ipstatus" style="text-align: center;">Flight</th>
|
||||
<th id="name">节点名</th>
|
||||
<th id="type">虚拟化</th>
|
||||
<th id="location">位置</th>
|
||||
<th id="uptime">在线时间</th>
|
||||
<th id="online_status" style="text-align: center;">🔗协议</th>
|
||||
<th id="month_traffic" style="text-align: center;">📊月流量↓|↑</th>
|
||||
<th id="name">📌节点</th>
|
||||
<th id="type">🗂️虚拟化</th>
|
||||
<th id="location">🌍位置</th>
|
||||
<th id="uptime">⏱️在线</th>
|
||||
<th id="load">负载</th>
|
||||
<th id="network">网络 ↓|↑</th>
|
||||
<th id="traffic">流量 ↓|↑</th>
|
||||
<th id="cpu">处理器</th>
|
||||
<th id="ram">内存</th>
|
||||
<th id="hdd">硬盘</th>
|
||||
<th id="ping">丢包率(CU|CT|CM)</th>
|
||||
<th id="network">🚦网络↓|↑</th>
|
||||
<th id="traffic">📋总流量↓|↑</th>
|
||||
<th id="cpu">🎯核芯</th>
|
||||
<th id="ram">⚡️内存</th>
|
||||
<th id="hdd">💾硬盘</th>
|
||||
<th id="ping">🌐CU|CT|CM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="servers">
|
||||
|
||||
4
web/js/jquery.min.js
vendored
4
web/js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
// serverstatus.js
|
||||
// serverstatus.js. big data boom today.
|
||||
var error = 0;
|
||||
var d = 0;
|
||||
var server_status = new Array();
|
||||
@@ -8,24 +8,9 @@ function timeSince(date) {
|
||||
return "从未.";
|
||||
|
||||
var seconds = Math.floor((new Date() - date) / 1000);
|
||||
var interval = Math.floor(seconds / 31536000);
|
||||
|
||||
if (interval > 1)
|
||||
return interval + " 年前.";
|
||||
interval = Math.floor(seconds / 2592000);
|
||||
if (interval > 1)
|
||||
return interval + " 月前.";
|
||||
interval = Math.floor(seconds / 86400);
|
||||
if (interval > 1)
|
||||
return interval + " 日前.";
|
||||
interval = Math.floor(seconds / 3600);
|
||||
if (interval > 1)
|
||||
return interval + " 小时前.";
|
||||
interval = Math.floor(seconds / 60);
|
||||
var interval = Math.floor(seconds / 60);
|
||||
if (interval > 1)
|
||||
return interval + " 分钟前.";
|
||||
/*if(Math.floor(seconds) >= 5)
|
||||
return Math.floor(seconds) + " seconds";*/
|
||||
else
|
||||
return "几秒前.";
|
||||
}
|
||||
@@ -35,24 +20,16 @@ function bytesToSize(bytes, precision, si)
|
||||
var ret;
|
||||
si = typeof si !== 'undefined' ? si : 0;
|
||||
if(si != 0) {
|
||||
var kilobyte = 1000;
|
||||
var megabyte = kilobyte * 1000;
|
||||
var megabyte = 1000 * 1000;
|
||||
var gigabyte = megabyte * 1000;
|
||||
var terabyte = gigabyte * 1000;
|
||||
} else {
|
||||
var kilobyte = 1024;
|
||||
var megabyte = kilobyte * 1024;
|
||||
var megabyte = 1024 * 1024;
|
||||
var gigabyte = megabyte * 1024;
|
||||
var terabyte = gigabyte * 1024;
|
||||
}
|
||||
|
||||
if ((bytes >= 0) && (bytes < kilobyte)) {
|
||||
return bytes + ' B';
|
||||
|
||||
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
|
||||
ret = (bytes / kilobyte).toFixed(precision) + ' K';
|
||||
|
||||
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
|
||||
if ((bytes >= megabyte) && (bytes < gigabyte)) {
|
||||
ret = (bytes / megabyte).toFixed(precision) + ' M';
|
||||
|
||||
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
|
||||
@@ -64,18 +41,19 @@ function bytesToSize(bytes, precision, si)
|
||||
} else {
|
||||
return bytes + ' B';
|
||||
}
|
||||
if(si != 0) {
|
||||
return ret;
|
||||
/*if(si != 0) {
|
||||
return ret + 'B';
|
||||
} else {
|
||||
return ret + 'iB';
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
function uptime() {
|
||||
$.getJSON("json/stats.json", function(result) {
|
||||
$("#loading-notice").remove();
|
||||
if(result.reload)
|
||||
setTimeout(function() { location.reload(true) }, 1000);
|
||||
setTimeout(function() { location.reload() }, 1000);
|
||||
|
||||
for (var i = 0, rlen=result.servers.length; i < rlen; i++) {
|
||||
var TableRow = $("#servers tr#r" + i);
|
||||
@@ -85,8 +63,8 @@ function uptime() {
|
||||
if (!TableRow.length) {
|
||||
$("#servers").append(
|
||||
"<tr id=\"r" + i + "\" data-toggle=\"collapse\" data-target=\"#rt" + i + "\" class=\"accordion-toggle " + hack + "\">" +
|
||||
"<td id=\"online4\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"ip_status\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"online_status\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"month_traffic\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"name\">加载中</td>" +
|
||||
"<td id=\"type\">加载中</td>" +
|
||||
"<td id=\"location\">加载中</td>" +
|
||||
@@ -101,10 +79,10 @@ function uptime() {
|
||||
"</tr>" +
|
||||
"<tr class=\"expandRow " + hack + "\"><td colspan=\"16\"><div class=\"accordian-body collapse\" id=\"rt" + i + "\">" +
|
||||
"<div id=\"expand_mem\">加载中</div>" +
|
||||
"<div id=\"expand_swap\">加载中</div>" +
|
||||
"<div id=\"expand_hdd\">加载中</div>" +
|
||||
"<div id=\"expand_tupd\">加载中</div>" +
|
||||
"<div id=\"expand_ping\">加载中</div>" +
|
||||
"<div id=\"expand_lost\">加载中</div>" +
|
||||
"<div id=\"expand_custom\">加载中</div>" +
|
||||
"</div></td></tr>"
|
||||
);
|
||||
@@ -118,38 +96,19 @@ function uptime() {
|
||||
server_status[i] = true;
|
||||
}
|
||||
|
||||
// Online4
|
||||
// online_status
|
||||
if (result.servers[i].online4 && !result.servers[i].online6) {
|
||||
TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online4"].children[0].children[0].innerHTML = "<small>IPv4</small>";
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>IPv4</small>";
|
||||
} else if (result.servers[i].online4 && result.servers[i].online6) {
|
||||
TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online4"].children[0].children[0].innerHTML = "<small>双栈</small>";
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>双栈</small>";
|
||||
} else if (!result.servers[i].online4 && result.servers[i].online6) {
|
||||
TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online4"].children[0].children[0].innerHTML = "<small>IPv6</small>";
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>IPv6</small>";
|
||||
} else {
|
||||
TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["online4"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
|
||||
// Online6
|
||||
//if (result.servers[i].online6) {
|
||||
// TableRow.children["online6"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
// TableRow.children["online6"].children[0].children[0].innerHTML = "<small>开启</small>";
|
||||
//} else {
|
||||
// TableRow.children["online6"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
// TableRow.children["online6"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
//}
|
||||
|
||||
// Ipstatus
|
||||
// mh361 or mh370, mourn mh370, 2014-03-08 01:20 lost from all over the world.
|
||||
if (result.servers[i].ip_status) {
|
||||
TableRow.children["ip_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["ip_status"].children[0].children[0].innerHTML = "<small>MH361</small>";
|
||||
} else {
|
||||
TableRow.children["ip_status"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["ip_status"].children[0].children[0].innerHTML = "<small>MH370</small>";
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
|
||||
// Name
|
||||
@@ -166,6 +125,8 @@ function uptime() {
|
||||
TableRow.children["load"].innerHTML = "–";
|
||||
TableRow.children["network"].innerHTML = "–";
|
||||
TableRow.children["traffic"].innerHTML = "–";
|
||||
TableRow.children["month_traffic"].children[0].children[0].className = "progress-bar progress-bar-warning";
|
||||
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["cpu"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["cpu"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
@@ -190,6 +151,22 @@ function uptime() {
|
||||
server_status[i] = true;
|
||||
}
|
||||
|
||||
// month traffic
|
||||
var monthtraffic = "";
|
||||
var trafficdiff_in = result.servers[i].network_in - result.servers[i].last_network_in;
|
||||
var trafficdiff_out = result.servers[i].network_out - result.servers[i].last_network_out;
|
||||
if(trafficdiff_in < 1024*1024*1024*1024)
|
||||
monthtraffic += (trafficdiff_in/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
monthtraffic += (trafficdiff_in/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
monthtraffic += " | "
|
||||
if(trafficdiff_out < 1024*1024*1024*1024)
|
||||
monthtraffic += (trafficdiff_out/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
monthtraffic += (trafficdiff_out/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
TableRow.children["month_traffic"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>"+monthtraffic+"</small>";
|
||||
|
||||
// Uptime
|
||||
TableRow.children["uptime"].innerHTML = result.servers[i].uptime;
|
||||
|
||||
@@ -202,44 +179,28 @@ function uptime() {
|
||||
|
||||
// Network
|
||||
var netstr = "";
|
||||
if(result.servers[i].network_rx < 1024)
|
||||
netstr += result.servers[i].network_rx.toFixed(0) + "B";
|
||||
else if(result.servers[i].network_rx < 1024*1024)
|
||||
netstr += (result.servers[i].network_rx/1024).toFixed(0) + "K";
|
||||
if(result.servers[i].network_rx < 1024*1024)
|
||||
netstr += (result.servers[i].network_rx/1024).toFixed(1) + "K";
|
||||
else
|
||||
netstr += (result.servers[i].network_rx/1024/1024).toFixed(1) + "M";
|
||||
netstr += " | "
|
||||
if(result.servers[i].network_tx < 1024)
|
||||
netstr += result.servers[i].network_tx.toFixed(0) + "B";
|
||||
else if(result.servers[i].network_tx < 1024*1024)
|
||||
netstr += (result.servers[i].network_tx/1024).toFixed(0) + "K";
|
||||
if(result.servers[i].network_tx < 1024*1024)
|
||||
netstr += (result.servers[i].network_tx/1024).toFixed(1) + "K";
|
||||
else
|
||||
netstr += (result.servers[i].network_tx/1024/1024).toFixed(1) + "M";
|
||||
TableRow.children["network"].innerHTML = netstr;
|
||||
|
||||
//Traffic
|
||||
var trafficstr = "";
|
||||
if(result.servers[i].network_in < 1024)
|
||||
trafficstr += result.servers[i].network_in.toFixed(0) + "B";
|
||||
else if(result.servers[i].network_in < 1024*1024)
|
||||
trafficstr += (result.servers[i].network_in/1024).toFixed(0) + "K";
|
||||
else if(result.servers[i].network_in < 1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_in/1024/1024).toFixed(1) + "M";
|
||||
else if(result.servers[i].network_in < 1024*1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_in/1024/1024/1024).toFixed(2) + "G";
|
||||
if(result.servers[i].network_in < 1024*1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_in/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
trafficstr += (result.servers[i].network_in/1024/1024/1024/1024).toFixed(2) + "T";
|
||||
trafficstr += (result.servers[i].network_in/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
trafficstr += " | "
|
||||
if(result.servers[i].network_out < 1024)
|
||||
trafficstr += result.servers[i].network_out.toFixed(0) + "B";
|
||||
else if(result.servers[i].network_out < 1024*1024)
|
||||
trafficstr += (result.servers[i].network_out/1024).toFixed(0) + "K";
|
||||
else if(result.servers[i].network_out < 1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_out/1024/1024).toFixed(1) + "M";
|
||||
else if(result.servers[i].network_out < 1024*1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_out/1024/1024/1024).toFixed(2) + "G";
|
||||
if(result.servers[i].network_out < 1024*1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_out/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
trafficstr += (result.servers[i].network_out/1024/1024/1024/1024).toFixed(2) + "T";
|
||||
trafficstr += (result.servers[i].network_out/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
TableRow.children["traffic"].innerHTML = trafficstr;
|
||||
|
||||
// CPU
|
||||
@@ -262,9 +223,8 @@ function uptime() {
|
||||
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["memory"].children[0].children[0].style.width = Mem + "%";
|
||||
TableRow.children["memory"].children[0].children[0].innerHTML = Mem + "%";
|
||||
ExpandRow[0].children["expand_mem"].innerHTML = "内存: " + bytesToSize(result.servers[i].memory_used*1024, 2) + " / " + bytesToSize(result.servers[i].memory_total*1024, 2);
|
||||
// Swap
|
||||
ExpandRow[0].children["expand_swap"].innerHTML = "交换分区: " + bytesToSize(result.servers[i].swap_used*1024, 2) + " / " + bytesToSize(result.servers[i].swap_total*1024, 2);
|
||||
// 内存|swap
|
||||
ExpandRow[0].children["expand_mem"].innerHTML = "内存|虚存: " + bytesToSize(result.servers[i].memory_used*1024, 1) + " / " + bytesToSize(result.servers[i].memory_total*1024, 1) + " | " + bytesToSize(result.servers[i].swap_used*1024, 0) + " / " + bytesToSize(result.servers[i].swap_total*1024, 0);
|
||||
|
||||
// HDD
|
||||
var HDD = ((result.servers[i].hdd_used/result.servers[i].hdd_total)*100.0).toFixed(0);
|
||||
@@ -276,7 +236,20 @@ function uptime() {
|
||||
TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["hdd"].children[0].children[0].style.width = HDD + "%";
|
||||
TableRow.children["hdd"].children[0].children[0].innerHTML = HDD + "%";
|
||||
ExpandRow[0].children["expand_hdd"].innerHTML = "硬盘: " + bytesToSize(result.servers[i].hdd_used*1024*1024, 2) + " / " + bytesToSize(result.servers[i].hdd_total*1024*1024, 2);
|
||||
// IO Speed for HDD.
|
||||
// IO, 过小的B字节单位没有意义
|
||||
var io = "";
|
||||
if(result.servers[i].io_read < 1024*1024)
|
||||
io += parseInt(result.servers[i].io_read/1024) + "K";
|
||||
else
|
||||
io += parseInt(result.servers[i].io_read/1024/1024) + "M";
|
||||
io += " / "
|
||||
if(result.servers[i].io_write < 1024*1024)
|
||||
io += parseInt(result.servers[i].io_write/1024) + "K";
|
||||
else
|
||||
io += parseInt(result.servers[i].io_write/1024/1024) + "M";
|
||||
// Expand for HDD.
|
||||
ExpandRow[0].children["expand_hdd"].innerHTML = "硬盘|读写: " + bytesToSize(result.servers[i].hdd_used*1024*1024, 2) + " / " + bytesToSize(result.servers[i].hdd_total*1024*1024, 2) + " | " + io;
|
||||
|
||||
// delay time
|
||||
|
||||
@@ -288,8 +261,12 @@ function uptime() {
|
||||
var PING_10010 = result.servers[i].ping_10010.toFixed(0);
|
||||
var PING_189 = result.servers[i].ping_189.toFixed(0);
|
||||
var PING_10086 = result.servers[i].ping_10086.toFixed(0);
|
||||
ExpandRow[0].children["expand_lost"].innerHTML = "丢包:联通/电信/移动: " + PING_10010 + "% / " + PING_189 + "% / " + PING_10086 + "%"
|
||||
|
||||
if (PING_10010 >= 20 || PING_189 >= 20 || PING_10086 >= 20)
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
else if (PING_10010 >= 10 || PING_189 >= 10 || PING_10086 >= 10)
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-warning";
|
||||
else
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["ping"].children[0].children[0].innerHTML = PING_10010 + "%💻" + PING_189 + "%💻" + PING_10086 + "%";
|
||||
@@ -310,12 +287,10 @@ function uptime() {
|
||||
$("#servers > tr.accordion-toggle").each(function(i) {
|
||||
var TableRow = $("#servers tr#r" + i)[0];
|
||||
var ExpandRow = $("#servers #rt" + i);
|
||||
TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["online4"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
//TableRow.children["online6"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
//TableRow.children["online6"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["ip_status"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["ip_status"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["month_traffic"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["uptime"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["uptime"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["load"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
@@ -360,14 +335,17 @@ setInterval(updateTime, 2000);
|
||||
|
||||
|
||||
// styleswitcher.js
|
||||
function setActiveStyleSheet(title) {
|
||||
var i, a, main;
|
||||
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
|
||||
a.disabled = true;
|
||||
if(a.getAttribute("title") == title) a.disabled = false;
|
||||
}
|
||||
}
|
||||
function setActiveStyleSheet(title, cookie=false) {
|
||||
var i, a, main;
|
||||
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
|
||||
a.disabled = true;
|
||||
if(a.getAttribute("title") == title) a.disabled = false;
|
||||
}
|
||||
}
|
||||
if (true==cookie) {
|
||||
createCookie("style", title, 365);
|
||||
}
|
||||
}
|
||||
|
||||
function getActiveStyleSheet() {
|
||||
@@ -379,15 +357,6 @@ function getActiveStyleSheet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPreferredStyleSheet() {
|
||||
var i, a;
|
||||
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("rel").indexOf("alt") == -1 && a.getAttribute("title"))
|
||||
return a.getAttribute("title");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function createCookie(name,value,days) {
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
@@ -412,16 +381,19 @@ function readCookie(name) {
|
||||
}
|
||||
|
||||
window.onload = function(e) {
|
||||
var cookie = readCookie("style");
|
||||
var title = cookie ? cookie : getPreferredStyleSheet();
|
||||
setActiveStyleSheet(title);
|
||||
var cookie = readCookie("style");
|
||||
if (cookie && cookie != 'null' ) {
|
||||
setActiveStyleSheet(cookie);
|
||||
} else {
|
||||
function handleChange (mediaQueryListEvent) {
|
||||
if (mediaQueryListEvent.matches) {
|
||||
setActiveStyleSheet('dark');
|
||||
} else {
|
||||
setActiveStyleSheet('light');
|
||||
}
|
||||
}
|
||||
const mediaQueryListDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
setActiveStyleSheet(mediaQueryListDark.matches ? 'dark' : 'light');
|
||||
mediaQueryListDark.addEventListener("change",handleChange);
|
||||
}
|
||||
}
|
||||
|
||||
window.onunload = function(e) {
|
||||
var title = getActiveStyleSheet();
|
||||
createCookie("style", title, 365);
|
||||
}
|
||||
|
||||
var cookie = readCookie("style");
|
||||
var title = cookie ? cookie : getPreferredStyleSheet();
|
||||
setActiveStyleSheet(title);
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# coding: utf-8
|
||||
# Update by : https://github.com/cppla/ServerStatus
|
||||
# 支持Python版本:2.7 to 3.5; requirements.txt: requests, PrettyTable
|
||||
# 时间: 20180828
|
||||
'''
|
||||
maybe better by youself
|
||||
'''
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20211009
|
||||
# 支持Python版本:2.7 to 3.9; requirements.txt: requests, PrettyTable
|
||||
# 主要是为了受到CC attack时候方便查看机器状态
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -13,9 +10,9 @@ import requests
|
||||
import time
|
||||
from prettytable import PrettyTable
|
||||
|
||||
# todo: 程序在非gui环境下目前有闪屏的bug
|
||||
scroll = True
|
||||
clear = lambda: os.system('clear' if 'linux' in sys.platform else 'cls')
|
||||
clear = lambda: os.system('clear' if 'linux' in sys.platform or 'darwin' in sys.platform else 'cls')
|
||||
|
||||
|
||||
def sscmd(address):
|
||||
while True:
|
||||
@@ -29,42 +26,58 @@ def sscmd(address):
|
||||
|
||||
ss = PrettyTable(
|
||||
[
|
||||
"Flight",
|
||||
"月流量 ↓|↑",
|
||||
"节点名",
|
||||
# "虚拟化",
|
||||
"位置",
|
||||
"在线时间",
|
||||
"负载",
|
||||
"网络",
|
||||
"流量",
|
||||
"网络 ↓|↑",
|
||||
"总流量 ↓|↑",
|
||||
"处理器",
|
||||
"内存",
|
||||
"硬盘"
|
||||
],
|
||||
)
|
||||
for i in jsonR["servers"]:
|
||||
ss.add_row(
|
||||
[
|
||||
"%s" % 'MH361' if i["ip_status"] is True else 'MH370',
|
||||
"%s" % i["name"],
|
||||
# "%s" % i["type"],
|
||||
"%s" % i["location"],
|
||||
"%s" % i["uptime"],
|
||||
"%s" % (i["load_1"]),
|
||||
"%.2fM|%.2fM" % (float(i["network_rx"]) / 1000 / 1000, float(i["network_tx"]) / 1000 / 1000),
|
||||
"%.2fG|%.2fG" % (
|
||||
float(i["network_in"]) / 1024 / 1024 / 1024, float(i["network_out"]) / 1024 / 1024 / 1024),
|
||||
"%d%%" % (i["cpu"]),
|
||||
"%d%%" % (float(i["memory_used"]) / i["memory_total"] * 100),
|
||||
"%d%%" % (float(i["hdd_used"]) / i["hdd_total"] * 100),
|
||||
]
|
||||
)
|
||||
if i["online4"] is False and i["online6"] is False:
|
||||
ss.add_row(
|
||||
[
|
||||
'0.00G',
|
||||
"%s" % i["name"],
|
||||
"%s" % i["location"],
|
||||
'-',
|
||||
'-',
|
||||
'-',
|
||||
'-',
|
||||
'-',
|
||||
'-',
|
||||
'-',
|
||||
]
|
||||
)
|
||||
else:
|
||||
ss.add_row(
|
||||
[
|
||||
"%.2fG|%.2fG" % (float(i["last_network_in"]) / 1024 / 1024 / 1024, float(i["last_network_out"]) / 1024 / 1024 / 1024),
|
||||
"%s" % i["name"],
|
||||
# "%s" % i["type"],
|
||||
"%s" % i["location"],
|
||||
"%s" % i["uptime"],
|
||||
"%s" % (i["load_1"]),
|
||||
"%.2fM|%.2fM" % (float(i["network_rx"]) / 1000 / 1000, float(i["network_tx"]) / 1000 / 1000),
|
||||
"%.2fG|%.2fG" % (
|
||||
float(i["network_in"]) / 1024 / 1024 / 1024, float(i["network_out"]) / 1024 / 1024 / 1024),
|
||||
"%d%%" % (i["cpu"]),
|
||||
"%d%%" % (float(i["memory_used"]) / i["memory_total"] * 100),
|
||||
"%d%%" % (float(i["hdd_used"]) / i["hdd_total"] * 100),
|
||||
]
|
||||
)
|
||||
if scroll is True:
|
||||
clear()
|
||||
print(ss)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
default = 'https://tz.cloudcpp.com/json/stats.json'
|
||||
ads = sys.argv[1] if len(sys.argv)==2 else default
|
||||
ads = sys.argv[1] if len(sys.argv) == 2 else default
|
||||
sscmd(ads)
|
||||
|
||||
Reference in New Issue
Block a user