123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- #!/usr/bin/env python3
- # coding: utf-8
- # 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
- # 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
- SERVER = "127.0.0.1"
- USER = "s01"
- PASSWORD = "USER_DEFAULT_PASSWORD"
- 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 re
- import os
- import sys
- import json
- import errno
- import subprocess
- import threading
- try:
- from queue import Queue # python3
- except ImportError:
- from Queue import Queue # python2
- def get_uptime():
- with open('/proc/uptime', 'r') as f:
- uptime = f.readline().split('.', 2)
- return int(uptime[0])
- def get_memory():
- re_parser = re.compile(r'^(?P<key>\S*):\s*(?P<value>\d*)\s*kB')
- result = dict()
- for line in open('/proc/meminfo'):
- match = re_parser.match(line)
- if not match:
- continue
- key, value = match.groups(['key', 'value'])
- result[key] = int(value)
- MemTotal = float(result['MemTotal'])
- MemUsed = MemTotal-float(result['MemFree'])-float(result['Buffers'])-float(result['Cached'])-float(result['SReclaimable'])
- SwapTotal = float(result['SwapTotal'])
- SwapFree = float(result['SwapFree'])
- return int(MemTotal), int(MemUsed), int(SwapTotal), int(SwapFree)
- def get_hdd():
- p = subprocess.check_output(['df', '-Tlm', '--total', '-t', 'ext4', '-t', 'ext3', '-t', 'ext2', '-t', 'reiserfs', '-t', 'jfs', '-t', 'ntfs', '-t', 'fat32', '-t', 'btrfs', '-t', 'fuseblk', '-t', 'zfs', '-t', 'simfs', '-t', 'xfs']).decode("Utf-8")
- total = p.splitlines()[-1]
- used = total.split()[3]
- size = total.split()[2]
- return int(size), int(used)
- def get_time():
- with open("/proc/stat", "r") as f:
- time_list = f.readline().split(' ')[2:6]
- for i in range(len(time_list)) :
- time_list[i] = int(time_list[i])
- return time_list
- def delta_time():
- x = get_time()
- time.sleep(INTERVAL)
- y = get_time()
- for i in range(len(x)):
- y[i]-=x[i]
- return y
- def get_cpu():
- t = delta_time()
- st = sum(t)
- if st == 0:
- st = 1
- result = 100-(t[len(t)-1]*100.00/st)
- return round(result, 1)
- def liuliang():
- NET_IN = 0
- NET_OUT = 0
- with open('/proc/net/dev') as f:
- for line in f.readlines():
- netinfo = re.findall('([^\s]+):[\s]{0,}(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)', line)
- if netinfo:
- if netinfo[0][0] == 'lo' or 'tun' in netinfo[0][0] \
- or 'docker' in netinfo[0][0] or 'veth' in netinfo[0][0] \
- or 'br-' in netinfo[0][0] or 'vmbr' in netinfo[0][0] \
- or 'vnet' in netinfo[0][0] or 'kube' in netinfo[0][0] \
- or netinfo[0][1]=='0' or netinfo[0][9]=='0':
- continue
- else:
- NET_IN += int(netinfo[0][1])
- NET_OUT += int(netinfo[0][9])
- return NET_IN, NET_OUT
- def tupd():
- '''
- tcp, udp, process, thread count: for view ddcc attack , then send warning
- :return:
- '''
- s = subprocess.check_output("ss -t|wc -l", shell=True)
- t = int(s[:-1])-1
- s = subprocess.check_output("ss -u|wc -l", shell=True)
- u = int(s[:-1])-1
- s = subprocess.check_output("ps -ef|wc -l", shell=True)
- p = int(s[:-1])-2
- s = subprocess.check_output("ps -eLf|wc -l", shell=True)
- d = int(s[:-1])-2
- return t,u,p,d
- def get_network(ip_version):
- if(ip_version == 4):
- HOST = "ipv4.google.com"
- elif(ip_version == 6):
- HOST = "ipv6.google.com"
- try:
- socket.create_connection((HOST, 80), 2).close()
- return True
- except:
- return False
- lostRate = {
- '10010': 0.0,
- '189': 0.0,
- '10086': 0.0
- }
- pingTime = {
- '10010': 0,
- '189': 0,
- '10086': 0
- }
- netSpeed = {
- 'netrx': 0.0,
- 'nettx': 0.0,
- 'clock': 0.0,
- 'diff': 0.0,
- '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:
- pass
- while True:
- if packet_queue.full():
- if packet_queue.get() == 0:
- lostPacket -= 1
- try:
- b = timeit.default_timer()
- socket.create_connection((IP, port), timeout=1).close()
- pingTime[mark] = int((timeit.default_timer() - b) * 1000)
- packet_queue.put(1)
- except socket.error as error:
- if error.errno == errno.ECONNREFUSED:
- pingTime[mark] = int((timeit.default_timer() - b) * 1000)
- packet_queue.put(1)
- #elif error.errno == errno.ETIMEDOUT:
- else:
- lostPacket += 1
- packet_queue.put(0)
- if packet_queue.qsize() > 30:
- lostRate[mark] = float(lostPacket) / packet_queue.qsize()
- time.sleep(INTERVAL)
- def _net_speed():
- while True:
- with open("/proc/net/dev", "r") as f:
- net_dev = f.readlines()
- avgrx = 0
- avgtx = 0
- for dev in net_dev[2:]:
- dev = dev.split(':')
- if "lo" in dev[0] or "tun" in dev[0] \
- or "docker" in dev[0] or "veth" in dev[0] \
- or "br-" in dev[0] or "vmbr" in dev[0] \
- or "vnet" in dev[0] or "kube" in dev[0]:
- continue
- dev = dev[1].split()
- avgrx += int(dev[0])
- avgtx += int(dev[8])
- now_clock = time.time()
- netSpeed["diff"] = now_clock - netSpeed["clock"]
- netSpeed["clock"] = now_clock
- netSpeed["netrx"] = int((avgrx - netSpeed["avgrx"]) / netSpeed["diff"])
- netSpeed["nettx"] = int((avgtx - netSpeed["avgtx"]) / netSpeed["diff"])
- netSpeed["avgrx"] = avgrx
- netSpeed["avgtx"] = avgtx
- time.sleep(INTERVAL)
- 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={
- 'host': CU,
- 'mark': '10010',
- 'port': PROBEPORT
- }
- )
- t2 = threading.Thread(
- target=_ping_thread,
- kwargs={
- 'host': CT,
- 'mark': '189',
- 'port': PROBEPORT
- }
- )
- t3 = threading.Thread(
- target=_ping_thread,
- kwargs={
- 'host': CM,
- 'mark': '10086',
- 'port': PROBEPORT
- }
- )
- t4 = threading.Thread(
- target=_net_speed,
- )
- t5 = threading.Thread(
- target=_disk_io,
- )
- for ti in [t1, t2, t3, t4, t5]:
- ti.daemon = True
- ti.start()
- def byte_str(object):
- '''
- bytes to str, str to bytes
- :param object:
- :return:
- '''
- if isinstance(object, str):
- return object.encode(encoding="utf-8")
- elif isinstance(object, bytes):
- return bytes.decode(object)
- else:
- print(type(object))
- if __name__ == '__main__':
- for argc in sys.argv:
- if 'SERVER' in argc:
- SERVER = argc.split('SERVER=')[-1]
- elif 'PORT' in argc:
- PORT = int(argc.split('PORT=')[-1])
- elif 'USER' in argc:
- USER = argc.split('USER=')[-1]
- elif 'PASSWORD' in argc:
- PASSWORD = argc.split('PASSWORD=')[-1]
- elif 'INTERVAL' in argc:
- INTERVAL = int(argc.split('INTERVAL=')[-1])
- socket.setdefaulttimeout(30)
- get_realtime_data()
- while True:
- try:
- print("Connecting...")
- s = socket.create_connection((SERVER, PORT))
- data = byte_str(s.recv(1024))
- if data.find("Authentication required") > -1:
- s.send(byte_str(USER + ':' + PASSWORD + '\n'))
- data = byte_str(s.recv(1024))
- if data.find("Authentication successful") < 0:
- print(data)
- raise socket.error
- else:
- print(data)
- raise socket.error
- print(data)
- if data.find("You are connecting via") < 0:
- data = byte_str(s.recv(1024))
- print(data)
- timer = 0
- check_ip = 0
- if data.find("IPv4") > -1:
- check_ip = 6
- elif data.find("IPv6") > -1:
- check_ip = 4
- else:
- print(data)
- raise socket.error
- while True:
- CPU = get_cpu()
- NET_IN, NET_OUT = liuliang()
- Uptime = get_uptime()
- Load_1, Load_5, Load_15 = os.getloadavg()
- MemoryTotal, MemoryUsed, SwapTotal, SwapFree = get_memory()
- HDDTotal, HDDUsed = get_hdd()
- array = {}
- if not timer:
- array['online' + str(check_ip)] = get_network(check_ip)
- timer = 10
- else:
- timer -= 1*INTERVAL
- array['uptime'] = Uptime
- array['load_1'] = Load_1
- array['load_5'] = Load_5
- array['load_15'] = Load_15
- array['memory_total'] = MemoryTotal
- array['memory_used'] = MemoryUsed
- array['swap_total'] = SwapTotal
- array['swap_used'] = SwapTotal - SwapFree
- array['hdd_total'] = HDDTotal
- array['hdd_used'] = HDDUsed
- array['cpu'] = CPU
- array['network_rx'] = netSpeed.get("netrx")
- array['network_tx'] = netSpeed.get("nettx")
- array['network_in'] = NET_IN
- array['network_out'] = NET_OUT
- # 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
- array['time_10010'] = pingTime.get('10010')
- 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:
- raise
- except socket.error:
- print("Disconnected...")
- if 's' in locals().keys():
- del s
- time.sleep(3)
- except Exception as e:
- print("Caught Exception:", e)
- if 's' in locals().keys():
- del s
- time.sleep(3)
|