Compare commits

..
Author SHA1 Message Date
cpplaandGitHub f43715ff25 Merge pull request #169 from balala2oo8/master
修复月流量匹配问题,用username当作key作为匹配月流量的依据

将其合并到分支usernameAsMonthTrafficKey,有喜欢这个版本的的可以使用。唯一的缺点会暴漏username。
2022-05-23 16:33:06 +08:00
balala 086cc5b96b 修复月流量匹配问题 2022-05-13 21:07:44 +08:00
15 changed files with 295 additions and 41323 deletions
+3 -7
View File
@@ -3,13 +3,13 @@ FROM debian:buster as builder
MAINTAINER cppla https://cpp.la MAINTAINER cppla https://cpp.la
RUN apt-get update -y && apt-get -y install gcc g++ make libcurl4-openssl-dev RUN apt-get update -y && apt-get -y install gcc g++ make
COPY . . COPY . .
WORKDIR /server WORKDIR /server
RUN make -j RUN make
RUN pwd && ls -a RUN pwd && ls -a
# glibc env run # glibc env run
@@ -20,10 +20,6 @@ RUN mkdir -p /ServerStatus/server/
COPY --from=builder server /ServerStatus/server/ COPY --from=builder server /ServerStatus/server/
COPY --from=builder web /usr/share/nginx/html/ 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 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' CMD nohup sh -c '/etc/init.d/nginx start && /ServerStatus/server/sergate --config=/ServerStatus/server/config.json --web-dir=/usr/share/nginx/html'
+49 -91
View File
@@ -3,16 +3,16 @@
* ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。 * ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。
* 在线演示:https://tz.cloudcpp.com * 在线演示:https://tz.cloudcpp.com
[![Python Support](https://img.shields.io/badge/python-3.6%2B%20-blue.svg)](https://github.com/cppla/ServerStatus) [![Python Support](https://img.shields.io/badge/python-2.7%2B%20-blue.svg)](https://github.com/cppla/ServerStatus)
[![C++ Compiler](http://img.shields.io/badge/C++-GNU-blue.svg?style=flat&logo=cplusplus)](https://github.com/cppla/ServerStatus) [![C++ Compiler](http://img.shields.io/badge/C++-GNU-blue.svg?style=flat&logo=cplusplus)](https://github.com/cppla/ServerStatus)
[![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg?style=flat-square)](https://github.com/cppla/ServerStatus) [![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg?style=flat-square)](https://github.com/cppla/ServerStatus)
[![Version](https://img.shields.io/badge/Version-Build%201.1.0-red)](https://github.com/cppla/ServerStatus) [![Version](https://img.shields.io/badge/Version-Beta%201.0.8-red)](https://github.com/cppla/ServerStatus)
![Latest Version](http://dl.cpp.la/Archive/serverstatus_1.0.9.png) ![Latest Version](http://dl.cpp.la/Archive/serverstatus-latest.png)
`Watchdog🐶已经加入,触发式告警。 interval只是为了防止频繁收到报警信息造成骚扰,并不是探测间隔。` `curl -sSL https://get.docker.com/ | sh && apt -y install docker-compose`
# 目录: # 目录介绍
* clients 客户端文件 * clients 客户端文件
* server 服务端文件 * server 服务端文件
@@ -21,17 +21,20 @@
* server/config.json 探针配置文件       * server/config.json 探针配置文件      
* web/json 探针月流量 * web/json 探针月流量
# 部署: # 自动部署:
【服务端】: 【服务端】:
```bash ```bash
`Docker`: `OneTouch`:
wget --no-check-certificate -qO ~/serverstatus-config.json https://raw.githubusercontent.com/cppla/ServerStatus/master/server/config.json && mkdir ~/serverstatus-monthtraffic 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 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
`Docker-compose(推荐)`: docker-compose up -d `ServerStatus`: docker-compose up -d
`ServerStatus with tgbot`: TG_CHAT_ID=你的电报ID TG_BOT_TOKEN=你的电报密钥 docker-compose -f docker-compose-telegram.yml up -d
``` ```
【客户端】: 【客户端】:
@@ -42,44 +45,27 @@ eg:
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 & 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 &
``` ```
# 主题:
* layuihttps://github.com/zeyudada/StatusServerLayui ,预览:https://sslt.8zyw.cn
<img src=https://dl.cpp.la/Archive/serverstatus_layui.png width=200 height=100 />
* lighthttps://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
``` ```
`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 【服务端配置】:
一、生成服务端程序
```
cd ServerStatus/server
make
./sergate ./sergate
``` ```
如果没错误提示,OK,ctrl+c关闭;如果有错误提示,检查35601端口是否被占用 如果没错误提示,OK,ctrl+c关闭;如果有错误提示,检查35601端口是否被占用
#### 二、修改配置文件 二、修改配置文件
```diff 修改config.json文件,注意username, password的值需要和客户端对应一致    
! 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", "username": "s01",
@@ -90,83 +76,55 @@ cd ServerStatus/server && make
"password": "USER_DEFAULT_PASSWORD", "password": "USER_DEFAULT_PASSWORD",
"monthstart": 1 "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 sudo cp -r ServerStatus/web/* /home/wwwroot/default
``` ```
#### 四、运行服务端: 四、运行服务端:
web-dir参数为上一步设置的网站根目录,务必修改成自己网站的路径 web-dir参数为上一步设置的网站根目录,务必修改成自己网站的路径
``` ```
./sergate --config=config.json --web-dir=/home/wwwroot/default ./sergate --config=config.json --web-dir=/home/wwwroot/default
``` ```
**【客户端配置】** 【客户端配置】:
客户端有两个版本,client-linux为普通linuxclient-psutil为跨平台版,普通版不成功,换成跨平台版即可。 客户端有两个版本,client-linux为普通linuxclient-psutil为跨平台版,普通版不成功,换成跨平台版即可。
#### 一、client-linux版配置: 一、client-linux版配置:
1、vim client-linux.py, 修改SERVER地址,username帐号, password密码 1、vim client-linux.py, 修改SERVER地址,username帐号, password密码
2、python3 client-linux.py 运行即可。 2、python3 client-linux.py 运行即可。
#### 二、client-psutil版配置: 二、client-psutil版配置:
1、安装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密码 2、vim client-psutil.py, 修改SERVER地址,username帐号, password密码
3、python3 client-psutil.py 运行即可。 3、python3 client-psutil.py 运行即可。
```
### for Centos
sudo yum -y install epel-release
sudo yum -y install python3-pip
sudo yum clean all
sudo yum -y install gcc
sudo yum -y install python3-devel
sudo pip3 install psutil
服务器和客户端自行加入开机启动,或进程守护,或后台方式运行。 例如: nohup python3 client-linux.py & ### for Ubuntu/Debian:
sudo apt -y install python3-pip
sudo pip3 install psutil
### for Windows:
地址:https://pypi.org/project/psutil/
下载psutil for windows, 安装即可
```
打开云探针页面,就可以正常的监控。接下来把服务器和客户端脚本自行加入开机启动,或者进程守护,或以后台方式运行即可!例如: nohup python3 client-linux.py &
`extra scene (run web/ssview.py)` `extra scene (run web/ssview.py)`
![Shell View](https://dl.cpp.la/Archive/serverstatus-shell.png?version=2023) ![Shell View](http://dl.cpp.la/Archive/serverstatus-shell.png)
# Make Better # Make Better
+12 -13
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8 # coding: utf-8
# Update by : https://github.com/cppla/ServerStatus, Update date: 20220530 # Update by : https://github.com/cppla/ServerStatus, Update date: 20220323
# 版本:1.0.3, 支持Python版本:2.7 to 3.10 # 版本:1.0.3, 支持Python版本:2.7 to 3.9
# 支持操作系统: Linux, OSX, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures # 支持操作系统: Linux, OSX, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。 # 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
@@ -155,18 +155,17 @@ def _ping_thread(host, mark, port):
lostPacket = 0 lostPacket = 0
packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN) packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN)
while True: IP = host
# flush dns , every time. if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname
IP = host try:
if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname if PROBE_PROTOCOL_PREFER == 'ipv4':
try: IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0]
if PROBE_PROTOCOL_PREFER == 'ipv4': else:
IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0] IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
else: except Exception:
IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
except Exception:
pass pass
while True:
if packet_queue.full(): if packet_queue.full():
if packet_queue.get() == 0: if packet_queue.get() == 0:
lostPacket -= 1 lostPacket -= 1
@@ -311,7 +310,7 @@ def get_realtime_data():
target=_disk_io, target=_disk_io,
) )
for ti in [t1, t2, t3, t4, t5]: for ti in [t1, t2, t3, t4, t5]:
ti.daemon = True ti.setDaemon(True)
ti.start() ti.start()
def byte_str(object): def byte_str(object):
+61 -81
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# coding: utf-8 # coding: utf-8
# Update by : https://github.com/cppla/ServerStatus, Update date: 20220530 # Update by : https://github.com/cppla/ServerStatus, Update date: 20220323
# 依赖于psutil跨平台库 # 依赖于psutil跨平台库
# 版本:1.0.3, 支持Python版本:2.7 to 3.10 # 版本:1.0.3, 支持Python版本:2.7 to 3.9
# 支持操作系统: Linux, Windows, OSX, Sun Solaris, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures # 支持操作系统: Linux, Windows, OSX, Sun Solaris, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。 # 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
@@ -46,22 +46,18 @@ def get_swap():
return int(Mem.total/1024.0), int(Mem.used/1024.0) return int(Mem.total/1024.0), int(Mem.used/1024.0)
def get_hdd(): def get_hdd():
if "darwin" in sys.platform: valid_fs = [ "ext4", "ext3", "ext2", "reiserfs", "jfs", "btrfs", "fuseblk", "zfs", "simfs", "ntfs", "fat32", "exfat", "xfs" ]
return int(psutil.disk_usage("/").total/1024.0/1024.0), int((psutil.disk_usage("/").total-psutil.disk_usage("/").free)/1024.0/1024.0) disks = dict()
else: size = 0
valid_fs = ["ext4", "ext3", "ext2", "reiserfs", "jfs", "btrfs", "fuseblk", "zfs", "simfs", "ntfs", "fat32", used = 0
"exfat", "xfs"] for disk in psutil.disk_partitions():
disks = dict() if not disk.device in disks and disk.fstype.lower() in valid_fs:
size = 0 disks[disk.device] = disk.mountpoint
used = 0 for disk in disks.values():
for disk in psutil.disk_partitions(): usage = psutil.disk_usage(disk)
if not disk.device in disks and disk.fstype.lower() in valid_fs: size += usage.total
disks[disk.device] = disk.mountpoint used += usage.used
for disk in disks.values(): return int(size/1024.0/1024.0), int(used/1024.0/1024.0)
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(): def get_cpu():
return psutil.cpu_percent(interval=INTERVAL) return psutil.cpu_percent(interval=INTERVAL)
@@ -92,23 +88,13 @@ def tupd():
u = int(os.popen('ss -u|wc -l').read()[:-1])-1 u = int(os.popen('ss -u|wc -l').read()[:-1])-1
p = int(os.popen('ps -ef|wc -l').read()[:-1])-2 p = int(os.popen('ps -ef|wc -l').read()[:-1])-2
d = int(os.popen('ps -eLf|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: elif sys.platform.startswith("win") is True:
t = int(os.popen('netstat -an|find "TCP" /c').read()[:-1])-1 t = int(os.popen('netstat -an|find "TCP" /c').read()[:-1])-1
u = int(os.popen('netstat -an|find "UDP" /c').read()[:-1])-1 u = int(os.popen('netstat -an|find "UDP" /c').read()[:-1])-1
p = len(psutil.pids()) p = len(psutil.pids())
# if you find cpu is high, please set d=0 d = 0
d = sum([psutil.Process(k).num_threads() for k in psutil.pids()]) # cpu is high, default: 0
# d = sum([psutil.Process(k).num_threads() for k in [x for x in psutil.pids()]])
else: else:
t,u,p,d = 0,0,0,0 t,u,p,d = 0,0,0,0
return t,u,p,d return t,u,p,d
@@ -153,18 +139,17 @@ def _ping_thread(host, mark, port):
lostPacket = 0 lostPacket = 0
packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN) packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN)
while True: IP = host
# flush dns, every time. if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname
IP = host try:
if host.count(':') < 1: # if not plain ipv6 address, means ipv4 address or hostname if PROBE_PROTOCOL_PREFER == 'ipv4':
try: IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0]
if PROBE_PROTOCOL_PREFER == 'ipv4': else:
IP = socket.getaddrinfo(host, None, socket.AF_INET)[0][4][0] IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
else: except Exception:
IP = socket.getaddrinfo(host, None, socket.AF_INET6)[0][4][0]
except Exception:
pass pass
while True:
if packet_queue.full(): if packet_queue.full():
if packet_queue.get() == 0: if packet_queue.get() == 0:
lostPacket -= 1 lostPacket -= 1
@@ -220,49 +205,44 @@ def _disk_io():
比如我这里是机械硬盘,大量做随机小文件读写,那么很低的读写也就能造成硬盘长时间的等待。 比如我这里是机械硬盘,大量做随机小文件读写,那么很低的读写也就能造成硬盘长时间的等待。
如果这里做连续性IO,那么普通机械硬盘写入到100Mb/s,那么也能造成硬盘长时间的等待。 如果这里做连续性IO,那么普通机械硬盘写入到100Mb/s,那么也能造成硬盘长时间的等待。
磁盘读写有误差:4k8k https://stackoverflow.com/questions/34413926/psutil-vs-dd-monitoring-disk-i-o 磁盘读写有误差:4k8k https://stackoverflow.com/questions/34413926/psutil-vs-dd-monitoring-disk-i-o
macos/win,暂不处理。
""" """
if "darwin" in sys.platform or "win" in sys.platform: while True:
diskIO["read"] = 0 # first get a list of all processes and disk io counters
diskIO["write"] = 0 procs = [p for p in psutil.process_iter()]
else: for p in procs[:]:
while True: try:
# first get a list of all processes and disk io counters p._before = p.io_counters()
procs = [p for p in psutil.process_iter()] except psutil.Error:
for p in procs[:]: 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: try:
p._before = p.io_counters() p._after = p.io_counters()
except psutil.Error: 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) procs.remove(p)
continue disks_after = psutil.disk_io_counters()
disks_before = psutil.disk_io_counters()
# sleep some time, only when INTERVAL==1 , io read/write per_sec. # finally calculate results by comparing data before and
# when INTERVAL > 1, io read/write per_INTERVAL # after the interval
time.sleep(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
# then retrieve the same info again diskIO["read"] = disks_after.read_bytes - disks_before.read_bytes
for p in procs[:]: diskIO["write"] = disks_after.write_bytes - disks_before.write_bytes
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(): def get_realtime_data():
''' '''
@@ -300,7 +280,7 @@ def get_realtime_data():
target=_disk_io, target=_disk_io,
) )
for ti in [t1, t2, t3, t4, t5]: for ti in [t1, t2, t3, t4, t5]:
ti.daemon = True ti.setDaemon(True)
ti.start() ti.start()
def byte_str(object): def byte_str(object):
@@ -364,7 +344,7 @@ if __name__ == '__main__':
CPU = get_cpu() CPU = get_cpu()
NET_IN, NET_OUT = liuliang() NET_IN, NET_OUT = liuliang()
Uptime = get_uptime() Uptime = get_uptime()
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) Load_1, Load_5, Load_15 = os.getloadavg() if 'linux' in sys.platform else (0.0, 0.0, 0.0)
MemoryTotal, MemoryUsed = get_memory() MemoryTotal, MemoryUsed = get_memory()
SwapTotal, SwapUsed = get_swap() SwapTotal, SwapUsed = get_swap()
HDDTotal, HDDUsed = get_hdd() HDDTotal, HDDUsed = get_hdd()
@@ -2,7 +2,7 @@ version: "3"
services: services:
serverstatus: serverstatus:
build: build:
context: .. context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: serverstatus_server image: serverstatus_server
container_name: serverstatus container_name: serverstatus
@@ -11,14 +11,14 @@ services:
serverstatus-network: serverstatus-network:
ipv4_address: 172.23.0.2 ipv4_address: 172.23.0.2
volumes: volumes:
- ../server/config.json:/ServerStatus/server/config.json - ./server/config.json:/ServerStatus/server/config.json
- ../web/json:/usr/share/nginx/html/json - ./web/json:/usr/share/nginx/html/json
ports: ports:
- 35601:35601 - 35601:35601
- 8080:80 - 8080:80
bot: bot:
build: build:
context: . context: ./plugin
dockerfile: Dockerfile-telegram dockerfile: Dockerfile-telegram
image: serverstatus_bot image: serverstatus_bot
container_name: bot4sss container_name: bot4sss
+2 -2
View File
@@ -6,7 +6,7 @@ CFLAGS = -Wall -O2
#CXX = clang++ #CXX = clang++
CXX = g++ CXX = g++
CXXFLAGS = -Wall -O2 -std=c++11 CXXFLAGS = -Wall -O2
ODIR = obj ODIR = obj
SDIR = src SDIR = src
@@ -26,7 +26,7 @@ $(ODIR)/%.o: $(SDIR)/%.cpp
$(CXX) -c $(INC) $(CXXFLAGS) $< -o $@ $(CXX) -c $(INC) $(CXXFLAGS) $< -o $@
$(OUT): $(OBJS) $(OUT): $(OBJS)
$(CXX) $(LIBS) $^ -o $(OUT) -lcurl $(CXX) $(LIBS) $^ -o $(OUT)
.PHONY: clean .PHONY: clean
+3 -41
View File
@@ -1,5 +1,5 @@
{ {"servers":
"servers": [ [
{ {
"username": "s01", "username": "s01",
"name": "node1", "name": "node1",
@@ -22,7 +22,7 @@
"disabled": true, "disabled": true,
"username": "s03", "username": "s03",
"name": "node3", "name": "node3",
"type": "hyper", "type": "Nothing",
"host": "host3", "host": "host3",
"location": "🇫🇷", "location": "🇫🇷",
"password": "USER_DEFAULT_PASSWORD", "password": "USER_DEFAULT_PASSWORD",
@@ -37,43 +37,5 @@
"password": "USER_DEFAULT_PASSWORD", "password": "USER_DEFAULT_PASSWORD",
"monthstart": 1 "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
View File
File diff suppressed because it is too large Load Diff
+10 -167
View File
@@ -7,8 +7,6 @@
#include <json.h> #include <json.h>
#include "server.h" #include "server.h"
#include "main.h" #include "main.h"
#include "exprtk.hpp"
#include "curl/curl.h"
#if defined(CONF_FAMILY_UNIX) #if defined(CONF_FAMILY_UNIX)
#include <signal.h> #include <signal.h>
@@ -98,13 +96,6 @@ void CMain::OnDelClient(int ClientNetID)
{ {
int ClientID = ClientNetToClient(ClientNetID); int ClientID = ClientNetToClient(ClientNetID);
dbg_msg("main", "OnDelClient(ncid=%d, cid=%d)", ClientNetID, ClientID); 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) if(ClientID >= 0 && ClientID < NET_MAX_CLIENTS)
{ {
Client(ClientID)->m_Connected = false; Client(ClientID)->m_Connected = false;
@@ -200,19 +191,6 @@ int CMain::HandleMessage(int ClientNetID, char *pMessage)
if(rStart["custom"].type == json_string) if(rStart["custom"].type == json_string)
str_copy(pClient->m_Stats.m_aCustom, rStart["custom"].u.string.ptr, sizeof(pClient->m_Stats.m_aCustom)); 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(m_Config.m_Verbose)
{ {
if(rStart["online4"].type) if(rStart["online4"].type)
@@ -256,113 +234,6 @@ int CMain::HandleMessage(int ClientNetID, char *pMessage)
return 1; 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(&currentStamp));
//url encode, Rules conflict with url special characterseg&, 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) void CMain::JSONUpdateThread(void *pUser)
{ {
CJSONUpdateThreadData *m_pJSONUpdateThreadData = (CJSONUpdateThreadData *)pUser; CJSONUpdateThreadData *m_pJSONUpdateThreadData = (CJSONUpdateThreadData *)pUser;
@@ -374,7 +245,7 @@ void CMain::JSONUpdateThread(void *pUser)
char aFileBuf[2048*NET_MAX_CLIENTS]; char aFileBuf[2048*NET_MAX_CLIENTS];
char *pBuf = aFileBuf; char *pBuf = aFileBuf;
str_format(pBuf, sizeof(aFileBuf), "{\n\"servers\": [\n"); str_format(pBuf, sizeof(aFileBuf), "{\n\"servers\": {\n");
pBuf += strlen(pBuf); pBuf += strlen(pBuf);
for(int i = 0; i < NET_MAX_CLIENTS; i++) for(int i = 0; i < NET_MAX_CLIENTS; i++)
@@ -407,7 +278,8 @@ void CMain::JSONUpdateThread(void *pUser)
} }
str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf), str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf),
"{ \"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", "\"%s\":{ \"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_aUsername,
pClients[i].m_aName,pClients[i].m_aType,pClients[i].m_aHost,pClients[i].m_aLocation, 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_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, 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,
@@ -424,16 +296,16 @@ void CMain::JSONUpdateThread(void *pUser)
{ {
// sava network traffic record to json when close client // sava network traffic record to json when close client
// last_network_in == last network in record, last_network_out == last network out record // 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", str_format(pBuf, sizeof(aFileBuf) - (pBuf - aFileBuf), "\"%s\":{ \"name\": \"%s\", \"type\": \"%s\", \"host\": \"%s\", \"location\": \"%s\", \"online4\": false, \"online6\": false, \"last_network_in\": %" PRId64 ", \"last_network_out\": %" PRId64 " },\n",pClients[i].m_aUsername,
pClients[i].m_aName, pClients[i].m_aType, pClients[i].m_aHost, pClients[i].m_aLocation, pClients[i].m_LastNetworkIN, pClients[i].m_LastNetworkOUT); 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); pBuf += strlen(pBuf);
} }
} }
if(!m_pJSONUpdateThreadData->m_ReloadRequired) if(!m_pJSONUpdateThreadData->m_ReloadRequired)
str_format(pBuf - 2, sizeof(aFileBuf) - (pBuf - aFileBuf), "\n],\n\"updated\": \"%lld\"\n}", (long long)time(/*ago*/0)); str_format(pBuf - 2, sizeof(aFileBuf) - (pBuf - aFileBuf), "\n},\n\"updated\": \"%lld\"\n}", (long long)time(/*ago*/0));
else else
{ {
str_format(pBuf - 2, sizeof(aFileBuf) - (pBuf - aFileBuf), "\n],\n\"updated\": \"%lld\",\n\"reload\": true\n}", (long long)time(/*ago*/0)); str_format(pBuf - 2, sizeof(aFileBuf) - (pBuf - aFileBuf), "\n},\n\"updated\": \"%lld\",\n\"reload\": true\n}", (long long)time(/*ago*/0));
m_pJSONUpdateThreadData->m_ReloadRequired--; m_pJSONUpdateThreadData->m_ReloadRequired--;
} }
pBuf += strlen(pBuf); pBuf += strlen(pBuf);
@@ -540,28 +412,6 @@ int CMain::ReadConfig()
} }
} }
// 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 recordreset m_LastNetworkIN and m_LastNetworkOUT // if file exists, read last network traffic recordreset m_LastNetworkIN and m_LastNetworkOUT
// support by: https://cpp.la // support by: https://cpp.la
IOHANDLE nFile = io_open(m_Config.m_aJSONFile, IOFLAG_READ); IOHANDLE nFile = io_open(m_Config.m_aJSONFile, IOFLAG_READ);
@@ -593,17 +443,11 @@ int CMain::ReadConfig()
{ {
if(ID < 0 || ID >= NET_MAX_CLIENTS) if(ID < 0 || ID >= NET_MAX_CLIENTS)
continue; continue;
for(unsigned j = 0; j < cStart.u.array.length; j++) char *uName = rStart[i]["username"].u.string.ptr;
if(strlen(cStart[uName]["name"]) != 0)
{ {
if(strcmp(Client(ID)->m_aName, cStart[j]["name"].u.string.ptr)==0 && Client(ID)->m_LastNetworkIN = cStart[uName]["last_network_in"].u.integer;
strcmp(Client(ID)->m_aType, cStart[j]["type"].u.string.ptr)==0 && Client(ID)->m_LastNetworkOUT = cStart[uName]["last_network_out"].u.integer;
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++; ID++;
} }
@@ -717,4 +561,3 @@ int main(int argc, const char *argv[])
return RetVal; return RetVal;
} }
+4 -20
View File
@@ -38,11 +38,10 @@ class CMain
char m_aPassword[128]; char m_aPassword[128];
int m_aMonthStart; //track month network traffic. by: https://cpp.la int m_aMonthStart; //track month network traffic. by: https://cpp.la
int64_t m_LastNetworkIN; //restore month traffic info. int64_t m_LastNetworkIN;
int64_t m_LastNetworkOUT; //restore month traffic info. int64_t m_LastNetworkOUT;
int64_t m_TimeConnected; int64 m_TimeConnected;
int64_t m_LastUpdate; int64 m_LastUpdate;
int64_t m_AlarmLastTime; //record last alarm time.
struct CStats struct CStats
{ {
@@ -83,13 +82,6 @@ class CMain
} m_Stats; } m_Stats;
} m_aClients[NET_MAX_CLIENTS]; } 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 struct CJSONUpdateThreadData
{ {
CClient *pClients; CClient *pClients;
@@ -107,14 +99,6 @@ public:
int ReadConfig(); int ReadConfig();
int Run(); 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 *Client(int ClientID) { return &m_aClients[ClientID]; }
CClient *ClientNet(int ClientNetID); CClient *ClientNet(int ClientNetID);
const CConfig *Config() const { return &m_Config; } const CConfig *Config() const { return &m_Config; }
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -4
View File
@@ -6,7 +6,6 @@ body { background: #212e36 url('../img/dark.png'); color: #dcdcdc; }
.dropdown-menu > li > a:hover { color: #FFF !important; background: #000 !important; } .dropdown-menu > li > a:hover { color: #FFF !important; background: #000 !important; }
.dropdown-menu { background: #222 !important; background-color: #222222 !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, #212e36, #212e36); background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); border-color: #252525; } .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; } .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 { background: #363b40; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
.table th { text-align: center; } .table th { text-align: center; }
@@ -19,11 +18,11 @@ tr.even.expandRow > :hover { background: #212e36 !important; }
tr.odd.expandRow > :hover { background: #212e36 !important; } tr.odd.expandRow > :hover { background: #212e36 !important; }
.expandRow > td { padding: 0 !important; border-top: 0px !important; } .expandRow > td { padding: 0 !important; border-top: 0px !important; }
#month_traffic { min-width: 85px; max-width: 95px;} #month_traffic { min-width: 85px; max-width: 95px;}
#network { min-width: 110px; } #network { min-width: 115px; }
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; } #cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
#ping { max-width: 110px; } #ping { max-width: 95px; }
@media only screen and (max-width: 1200px) { @media only screen and (max-width: 1080px) {
#type, tr td:nth-child(4) { display:none; visibility:hidden; } #type, tr td:nth-child(4) { display:none; visibility:hidden; }
#location, tr td:nth-child(5) { display:none; visibility:hidden; } #location, tr td:nth-child(5) { display:none; visibility:hidden; }
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; } #uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
+3 -4
View File
@@ -3,7 +3,6 @@ body { background: #ebebeb url('../img/light.png'); }
.navbar-brand { color: #fff; padding: 10px; font-size: 20px; } .navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; } .dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
.navbar-inverse .navbar-brand { color: #fff; padding: 10px; font-size: 20px; } .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; } .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 { background: #ffffff; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
.table th, .table td { text-align: center; } .table th, .table td { text-align: center; }
@@ -16,11 +15,11 @@ tr.even.expandRow > :hover { background: #F9F9F9 !important; }
tr.odd.expandRow > :hover { background: #FFF !important; } tr.odd.expandRow > :hover { background: #FFF !important; }
.expandRow > td { padding: 0 !important; border-top: 0px !important; } .expandRow > td { padding: 0 !important; border-top: 0px !important; }
#month_traffic { min-width: 85px; max-width: 95px;} #month_traffic { min-width: 85px; max-width: 95px;}
#network { min-width: 110px; } #network { min-width: 115px; }
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; } #cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
#ping { max-width: 110px; } #ping { max-width: 95px; }
@media only screen and (max-width: 1200px) { @media only screen and (max-width: 1080px) {
#type, tr td:nth-child(4) { display:none; visibility:hidden; } #type, tr td:nth-child(4) { display:none; visibility:hidden; }
#location, tr td:nth-child(5) { display:none; visibility:hidden; } #location, tr td:nth-child(5) { display:none; visibility:hidden; }
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; } #uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
+2 -2
View File
File diff suppressed because one or more lines are too long
+138 -140
View File
@@ -4,7 +4,7 @@ var d = 0;
var server_status = new Array(); var server_status = new Array();
function timeSince(date) { function timeSince(date) {
if(date == 0) if (date == 0)
return "从未."; return "从未.";
var seconds = Math.floor((new Date() - date) / 1000); var seconds = Math.floor((new Date() - date) / 1000);
@@ -15,11 +15,10 @@ function timeSince(date) {
return "几秒前."; return "几秒前.";
} }
function bytesToSize(bytes, precision, si) function bytesToSize(bytes, precision, si) {
{
var ret; var ret;
si = typeof si !== 'undefined' ? si : 0; si = typeof si !== 'undefined' ? si : 0;
if(si != 0) { if (si != 0) {
var megabyte = 1000 * 1000; var megabyte = 1000 * 1000;
var gigabyte = megabyte * 1000; var gigabyte = megabyte * 1000;
var terabyte = gigabyte * 1000; var terabyte = gigabyte * 1000;
@@ -50,40 +49,41 @@ function bytesToSize(bytes, precision, si)
} }
function uptime() { function uptime() {
$.getJSON("json/stats.json", function(result) { $.getJSON("json/stats.json", function (result) {
$("#loading-notice").remove(); $("#loading-notice").remove();
if(result.reload) if (result.reload)
setTimeout(function() { location.reload() }, 1000); setTimeout(function () { location.reload() }, 1000);
for (var i = 0, rlen=result.servers.length; i < rlen; i++) { let i = 0;
for (let key in result.servers) {
var TableRow = $("#servers tr#r" + i); var TableRow = $("#servers tr#r" + i);
var ExpandRow = $("#servers #rt" + i); var ExpandRow = $("#servers #rt" + i);
var hack; // fuck CSS for making me do this var hack; // fuck CSS for making me do this
if(i%2) hack="odd"; else hack="even"; if (i % 2) hack = "odd"; else hack = "even";
if (!TableRow.length) { if (!TableRow.length) {
$("#servers").append( $("#servers").append(
"<tr id=\"r" + i + "\" data-toggle=\"collapse\" data-target=\"#rt" + i + "\" class=\"accordion-toggle " + hack + "\">" + "<tr id=\"r" + i + "\" data-toggle=\"collapse\" data-target=\"#rt" + i + "\" class=\"accordion-toggle " + hack + "\">" +
"<td id=\"online_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=\"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=\"name\">加载中</td>" +
"<td id=\"type\">加载中</td>" + "<td id=\"type\">加载中</td>" +
"<td id=\"location\">加载中</td>" + "<td id=\"location\">加载中</td>" +
"<td id=\"uptime\">加载中</td>" + "<td id=\"uptime\">加载中</td>" +
"<td id=\"load\">加载中</td>" + "<td id=\"load\">加载中</td>" +
"<td id=\"network\">加载中</td>" + "<td id=\"network\">加载中</td>" +
"<td id=\"traffic\">加载中</td>" + "<td id=\"traffic\">加载中</td>" +
"<td id=\"cpu\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" + "<td id=\"cpu\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
"<td id=\"memory\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" + "<td id=\"memory\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
"<td id=\"hdd\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" + "<td id=\"hdd\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
"<td id=\"ping\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" + "<td id=\"ping\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
"</tr>" + "</tr>" +
"<tr class=\"expandRow " + hack + "\"><td colspan=\"16\"><div class=\"accordian-body collapse\" id=\"rt" + i + "\">" + "<tr class=\"expandRow " + hack + "\"><td colspan=\"16\"><div class=\"accordian-body collapse\" id=\"rt" + i + "\">" +
"<div id=\"expand_mem\">加载中</div>" + "<div id=\"expand_mem\">加载中</div>" +
"<div id=\"expand_hdd\">加载中</div>" + "<div id=\"expand_swap\">加载中</div>" +
"<div id=\"expand_tupd\">加载中</div>" + "<div id=\"expand_hdd\">加载中</div>" +
"<div id=\"expand_ping\">加载中</div>" + "<div id=\"expand_tupd\">加载中</div>" +
"<div id=\"expand_lost\">加载中</div>" + "<div id=\"expand_ping\">加载中</div>" +
"<div id=\"expand_custom\">加载中</div>" + "<div id=\"expand_custom\">加载中</div>" +
"</div></td></tr>" "</div></td></tr>"
); );
TableRow = $("#servers tr#r" + i); TableRow = $("#servers tr#r" + i);
@@ -91,20 +91,20 @@ function uptime() {
server_status[i] = true; server_status[i] = true;
} }
TableRow = TableRow[0]; TableRow = TableRow[0];
if(error) { if (error) {
TableRow.setAttribute("data-target", "#rt" + i); TableRow.setAttribute("data-target", "#rt" + i);
server_status[i] = true; server_status[i] = true;
} }
// online_status // online_status
if (result.servers[i].online4 && !result.servers[i].online6) { if (result.servers[key].online4 && !result.servers[key].online6) {
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success"; 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>"; TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>IPv4</small>";
} else if (result.servers[i].online4 && result.servers[i].online6) { } else if (result.servers[key].online4 && result.servers[key].online6) {
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success"; 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>"; TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>双栈</small>";
} else if (!result.servers[i].online4 && result.servers[i].online6) { } else if (!result.servers[key].online4 && result.servers[key].online6) {
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success"; 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>"; TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>IPv6</small>";
} else { } else {
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-danger"; TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-danger";
@@ -112,20 +112,20 @@ function uptime() {
} }
// Name // Name
TableRow.children["name"].innerHTML = result.servers[i].name; TableRow.children["name"].innerHTML = result.servers[key].name;
// Type // Type
TableRow.children["type"].innerHTML = result.servers[i].type; TableRow.children["type"].innerHTML = result.servers[key].type;
// Location // Location
TableRow.children["location"].innerHTML = result.servers[i].location; TableRow.children["location"].innerHTML = result.servers[key].location;
if (!result.servers[i].online4 && !result.servers[i].online6) { if (!result.servers[key].online4 && !result.servers[key].online6) {
if (server_status[i]) { if (server_status[i]) {
TableRow.children["uptime"].innerHTML = ""; TableRow.children["uptime"].innerHTML = "";
TableRow.children["load"].innerHTML = ""; TableRow.children["load"].innerHTML = "";
TableRow.children["network"].innerHTML = ""; TableRow.children["network"].innerHTML = "";
TableRow.children["traffic"].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].className = "progress-bar progress-bar-danger";
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>关闭</small>"; 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].className = "progress-bar progress-bar-danger";
TableRow.children["cpu"].children[0].children[0].style.width = "100%"; TableRow.children["cpu"].children[0].children[0].style.width = "100%";
@@ -139,7 +139,7 @@ function uptime() {
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-danger"; TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-danger";
TableRow.children["ping"].children[0].children[0].style.width = "100%"; TableRow.children["ping"].children[0].children[0].style.width = "100%";
TableRow.children["ping"].children[0].children[0].innerHTML = "<small>关闭</small>"; TableRow.children["ping"].children[0].children[0].innerHTML = "<small>关闭</small>";
if(ExpandRow.hasClass("in")) { if (ExpandRow.hasClass("in")) {
ExpandRow.collapse("hide"); ExpandRow.collapse("hide");
} }
TableRow.setAttribute("data-target", ""); TableRow.setAttribute("data-target", "");
@@ -153,68 +153,68 @@ function uptime() {
// month traffic // month traffic
var monthtraffic = ""; var monthtraffic = "";
var trafficdiff_in = result.servers[i].network_in - result.servers[i].last_network_in; var trafficdiff_in = result.servers[key].network_in - result.servers[key].last_network_in;
var trafficdiff_out = result.servers[i].network_out - result.servers[i].last_network_out; var trafficdiff_out = result.servers[key].network_out - result.servers[key].last_network_out;
if(trafficdiff_in < 1024*1024*1024*1024) if (trafficdiff_in < 1024 * 1024 * 1024 * 1024)
monthtraffic += (trafficdiff_in/1024/1024/1024).toFixed(1) + "G"; monthtraffic += (trafficdiff_in / 1024 / 1024 / 1024).toFixed(1) + "G";
else else
monthtraffic += (trafficdiff_in/1024/1024/1024/1024).toFixed(1) + "T"; monthtraffic += (trafficdiff_in / 1024 / 1024 / 1024 / 1024).toFixed(1) + "T";
monthtraffic += " | " monthtraffic += " | "
if(trafficdiff_out < 1024*1024*1024*1024) if (trafficdiff_out < 1024 * 1024 * 1024 * 1024)
monthtraffic += (trafficdiff_out/1024/1024/1024).toFixed(1) + "G"; monthtraffic += (trafficdiff_out / 1024 / 1024 / 1024).toFixed(1) + "G";
else else
monthtraffic += (trafficdiff_out/1024/1024/1024/1024).toFixed(1) + "T"; 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].className = "progress-bar progress-bar-success";
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>"+monthtraffic+"</small>"; TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>" + monthtraffic + "</small>";
// Uptime // Uptime
TableRow.children["uptime"].innerHTML = result.servers[i].uptime; TableRow.children["uptime"].innerHTML = result.servers[key].uptime;
// Load: default load_1, you can change show: load_1, load_5, load_15 // Load: default load_1, you can change show: load_1, load_5, load_15
if(result.servers[i].load == -1) { if (result.servers[key].load == -1) {
TableRow.children["load"].innerHTML = ""; TableRow.children["load"].innerHTML = "";
} else { } else {
TableRow.children["load"].innerHTML = result.servers[i].load_1.toFixed(2); TableRow.children["load"].innerHTML = result.servers[key].load_1.toFixed(2);
} }
// Network // Network
var netstr = ""; var netstr = "";
if(result.servers[i].network_rx < 1024*1024) if (result.servers[key].network_rx < 1024 * 1024)
netstr += (result.servers[i].network_rx/1024).toFixed(1) + "K"; netstr += (result.servers[key].network_rx / 1024).toFixed(1) + "K";
else else
netstr += (result.servers[i].network_rx/1024/1024).toFixed(1) + "M"; netstr += (result.servers[key].network_rx / 1024 / 1024).toFixed(1) + "M";
netstr += " | " netstr += " | "
if(result.servers[i].network_tx < 1024*1024) if (result.servers[key].network_tx < 1024 * 1024)
netstr += (result.servers[i].network_tx/1024).toFixed(1) + "K"; netstr += (result.servers[key].network_tx / 1024).toFixed(1) + "K";
else else
netstr += (result.servers[i].network_tx/1024/1024).toFixed(1) + "M"; netstr += (result.servers[key].network_tx / 1024 / 1024).toFixed(1) + "M";
TableRow.children["network"].innerHTML = netstr; TableRow.children["network"].innerHTML = netstr;
//Traffic //Traffic
var trafficstr = ""; var trafficstr = "";
if(result.servers[i].network_in < 1024*1024*1024*1024) if (result.servers[key].network_in < 1024 * 1024 * 1024 * 1024)
trafficstr += (result.servers[i].network_in/1024/1024/1024).toFixed(1) + "G"; trafficstr += (result.servers[key].network_in / 1024 / 1024 / 1024).toFixed(1) + "G";
else
trafficstr += (result.servers[i].network_in/1024/1024/1024/1024).toFixed(1) + "T";
trafficstr += " | "
if(result.servers[i].network_out < 1024*1024*1024*1024)
trafficstr += (result.servers[i].network_out/1024/1024/1024).toFixed(1) + "G";
else else
trafficstr += (result.servers[i].network_out/1024/1024/1024/1024).toFixed(1) + "T"; trafficstr += (result.servers[key].network_in / 1024 / 1024 / 1024 / 1024).toFixed(1) + "T";
trafficstr += " | "
if (result.servers[key].network_out < 1024 * 1024 * 1024 * 1024)
trafficstr += (result.servers[key].network_out / 1024 / 1024 / 1024).toFixed(1) + "G";
else
trafficstr += (result.servers[key].network_out / 1024 / 1024 / 1024 / 1024).toFixed(1) + "T";
TableRow.children["traffic"].innerHTML = trafficstr; TableRow.children["traffic"].innerHTML = trafficstr;
// CPU // CPU
if (result.servers[i].cpu >= 90) if (result.servers[key].cpu >= 90)
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-danger"; TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-danger";
else if (result.servers[i].cpu >= 80) else if (result.servers[key].cpu >= 80)
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-warning"; TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-warning";
else else
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-success"; TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-success";
TableRow.children["cpu"].children[0].children[0].style.width = result.servers[i].cpu + "%"; TableRow.children["cpu"].children[0].children[0].style.width = result.servers[key].cpu + "%";
TableRow.children["cpu"].children[0].children[0].innerHTML = result.servers[i].cpu + "%"; TableRow.children["cpu"].children[0].children[0].innerHTML = result.servers[key].cpu + "%";
// Memory // Memory
var Mem = ((result.servers[i].memory_used/result.servers[i].memory_total)*100.0).toFixed(0); var Mem = ((result.servers[key].memory_used / result.servers[key].memory_total) * 100.0).toFixed(0);
if (Mem >= 90) if (Mem >= 90)
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-danger"; TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-danger";
else if (Mem >= 80) else if (Mem >= 80)
@@ -223,11 +223,12 @@ function uptime() {
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-success"; 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].style.width = Mem + "%";
TableRow.children["memory"].children[0].children[0].innerHTML = Mem + "%"; TableRow.children["memory"].children[0].children[0].innerHTML = Mem + "%";
// 内存|swap ExpandRow[0].children["expand_mem"].innerHTML = "内存: " + bytesToSize(result.servers[key].memory_used * 1024, 2) + " / " + bytesToSize(result.servers[key].memory_total * 1024, 2);
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); // Swap
ExpandRow[0].children["expand_swap"].innerHTML = "交换分区: " + bytesToSize(result.servers[key].swap_used * 1024, 2) + " / " + bytesToSize(result.servers[key].swap_total * 1024, 2);
// HDD // HDD
var HDD = ((result.servers[i].hdd_used/result.servers[i].hdd_total)*100.0).toFixed(0); var HDD = ((result.servers[key].hdd_used / result.servers[key].hdd_total) * 100.0).toFixed(0);
if (HDD >= 90) if (HDD >= 90)
TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-danger"; TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-danger";
else if (HDD >= 80) else if (HDD >= 80)
@@ -239,52 +240,49 @@ function uptime() {
// IO Speed for HDD. // IO Speed for HDD.
// IO, 过小的B字节单位没有意义 // IO, 过小的B字节单位没有意义
var io = ""; var io = "";
if(result.servers[i].io_read < 1024*1024) if (result.servers[key].io_read < 1024 * 1024)
io += parseInt(result.servers[i].io_read/1024) + "K"; io += parseInt(result.servers[key].io_read / 1024) + "K";
else else
io += parseInt(result.servers[i].io_read/1024/1024) + "M"; io += parseInt(result.servers[key].io_read / 1024 / 1024) + "M";
io += " / " io += " / "
if(result.servers[i].io_write < 1024*1024) if (result.servers[key].io_write < 1024 * 1024)
io += parseInt(result.servers[i].io_write/1024) + "K"; io += parseInt(result.servers[key].io_write / 1024) + "K";
else else
io += parseInt(result.servers[i].io_write/1024/1024) + "M"; io += parseInt(result.servers[key].io_write / 1024 / 1024) + "M";
// Expand for HDD. // 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; ExpandRow[0].children["expand_hdd"].innerHTML = "硬盘|读写: " + bytesToSize(result.servers[key].hdd_used * 1024 * 1024, 2) + " / " + bytesToSize(result.servers[key].hdd_total * 1024 * 1024, 2) + " | " + io;
// delay time // delay time
// tcp, udp, process, thread count // tcp, udp, process, thread count
ExpandRow[0].children["expand_tupd"].innerHTML = "TCP/UDP/进/线: " + result.servers[i].tcp_count + " / " + result.servers[i].udp_count + " / " + result.servers[i].process_count+ " / " + result.servers[i].thread_count; ExpandRow[0].children["expand_tupd"].innerHTML = "TCP/UDP/进/线: " + result.servers[key].tcp_count + " / " + result.servers[key].udp_count + " / " + result.servers[key].process_count + " / " + result.servers[key].thread_count;
ExpandRow[0].children["expand_ping"].innerHTML = "联通/电信/移动: " + result.servers[i].time_10010 + "ms / " + result.servers[i].time_189 + "ms / " + result.servers[i].time_10086 + "ms" ExpandRow[0].children["expand_ping"].innerHTML = "联通/电信/移动: " + result.servers[key].time_10010 + "ms / " + result.servers[key].time_189 + "ms / " + result.servers[key].time_10086 + "ms"
// ping // ping
var PING_10010 = result.servers[i].ping_10010.toFixed(0); var PING_10010 = result.servers[key].ping_10010.toFixed(0);
var PING_189 = result.servers[i].ping_189.toFixed(0); var PING_189 = result.servers[key].ping_189.toFixed(0);
var PING_10086 = result.servers[i].ping_10086.toFixed(0); var PING_10086 = result.servers[key].ping_10086.toFixed(0);
ExpandRow[0].children["expand_lost"].innerHTML = "丢包:联通/电信/移动: " + PING_10010 + "% / " + PING_189 + "% / " + PING_10086 + "%" if (PING_10010 >= 70 || PING_189 >= 70 || PING_10086 >= 70)
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-warning";
if (PING_10010 >= 20 || PING_189 >= 20 || PING_10086 >= 20) else
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-danger"; TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-success";
else if (PING_10010 >= 10 || PING_189 >= 10 || PING_10086 >= 10) TableRow.children["ping"].children[0].children[0].innerHTML = PING_10010 + "-" + PING_189 + "-" + PING_10086 + "";
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 + "%";
// Custom // Custom
if (result.servers[i].custom) { if (result.servers[key].custom) {
ExpandRow[0].children["expand_custom"].innerHTML = result.servers[i].custom ExpandRow[0].children["expand_custom"].innerHTML = result.servers[key].custom
} else { } else {
ExpandRow[0].children["expand_custom"].innerHTML = "" ExpandRow[0].children["expand_custom"].innerHTML = ""
} }
} }
i++;
}; };
d = new Date(result.updated*1000); d = new Date(result.updated * 1000);
error = 0; error = 0;
}).fail(function(update_error) { }).fail(function (update_error) {
if (!error) { if (!error) {
$("#servers > tr.accordion-toggle").each(function(i) { $("#servers > tr.accordion-toggle").each(function (i) {
var TableRow = $("#servers tr#r" + i)[0]; var TableRow = $("#servers tr#r" + i)[0];
var ExpandRow = $("#servers #rt" + i); var ExpandRow = $("#servers #rt" + i);
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-error"; TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-error";
@@ -311,7 +309,7 @@ function uptime() {
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-error"; TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-error";
TableRow.children["ping"].children[0].children[0].style.width = "100%"; TableRow.children["ping"].children[0].children[0].style.width = "100%";
TableRow.children["ping"].children[0].children[0].innerHTML = "<small>错误</small>"; TableRow.children["ping"].children[0].children[0].innerHTML = "<small>错误</small>";
if(ExpandRow.hasClass("in")) { if (ExpandRow.hasClass("in")) {
ExpandRow.collapse("hide"); ExpandRow.collapse("hide");
} }
TableRow.setAttribute("data-target", ""); TableRow.setAttribute("data-target", "");
@@ -335,65 +333,65 @@ setInterval(updateTime, 2000);
// styleswitcher.js // styleswitcher.js
function setActiveStyleSheet(title, cookie=false) { function setActiveStyleSheet(title, cookie = false) {
var i, a, main; var i, a, main;
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) { for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) { if (a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
a.disabled = true; a.disabled = true;
if(a.getAttribute("title") == title) a.disabled = false; if (a.getAttribute("title") == title) a.disabled = false;
} }
} }
if (true==cookie) { if (true == cookie) {
createCookie("style", title, 365); createCookie("style", title, 365);
} }
} }
function getActiveStyleSheet() { function getActiveStyleSheet() {
var i, a; var i, a;
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) { for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) if (a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled)
return a.getAttribute("title"); return a.getAttribute("title");
} }
return null; return null;
} }
function createCookie(name,value,days) { function createCookie(name, value, days) {
if (days) { if (days) {
var date = new Date(); var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000)); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
var expires = "; expires="+date.toGMTString(); var expires = "; expires=" + date.toGMTString();
} }
else expires = ""; else expires = "";
document.cookie = name+"="+value+expires+"; path=/"; document.cookie = name + "=" + value + expires + "; path=/";
} }
function readCookie(name) { function readCookie(name) {
var nameEQ = name + "="; var nameEQ = name + "=";
var ca = document.cookie.split(';'); var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) { for (var i = 0; i < ca.length; i++) {
var c = ca[i]; var c = ca[i];
while (c.charAt(0)==' ') while (c.charAt(0) == ' ')
c = c.substring(1,c.length); c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) if (c.indexOf(nameEQ) == 0)
return c.substring(nameEQ.length,c.length); return c.substring(nameEQ.length, c.length);
} }
return null; return null;
} }
window.onload = function(e) { window.onload = function (e) {
var cookie = readCookie("style"); var cookie = readCookie("style");
if (cookie && cookie != 'null' ) { if (cookie && cookie != 'null') {
setActiveStyleSheet(cookie); setActiveStyleSheet(cookie);
} else { } else {
function handleChange (mediaQueryListEvent) { function handleChange(mediaQueryListEvent) {
if (mediaQueryListEvent.matches) { if (mediaQueryListEvent.matches) {
setActiveStyleSheet('dark'); setActiveStyleSheet('dark');
} else { } else {
setActiveStyleSheet('light'); setActiveStyleSheet('light');
} }
} }
const mediaQueryListDark = window.matchMedia('(prefers-color-scheme: dark)'); const mediaQueryListDark = window.matchMedia('(prefers-color-scheme: dark)');
setActiveStyleSheet(mediaQueryListDark.matches ? 'dark' : 'light'); setActiveStyleSheet(mediaQueryListDark.matches ? 'dark' : 'light');
mediaQueryListDark.addEventListener("change",handleChange); mediaQueryListDark.addEventListener("change", handleChange);
} }
} }