工作之余,为了方便,继续完善了网络监测程序(:
1、监测端:c#开发,目前实现了设备维护,监测,比如ping,snmp特性监测,模拟telnet等, 发现设备故障时可以二次验证,可以自由拓展,监测速度快,结果进日志及统计,同时第一时间短信及邮件通知维护人员。
2、订阅者:第一次用python增加了监控中心 订阅者,可以实时监视各 监测软件运行情况。
整体思路及效果,python订阅者代码分享
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""
网络巡检程序消息订阅程序
ver:3.0
"""
__author__ = 'wyw308'
__date__ = '2018.11.18'
import socket,winsound
import sys,os,time
import configparser
from threading import Timer
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 定义全局订阅通道s,ipv4 SOCK_DGRAM指定了这个Socket的类型是UDP
s_cmd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # cmd通道
orderMode = 'err' # 输出显现类型,all全部,err只显示告警信息
def send_msg(ip, port, msg):
"""发送数据到对应的ip和端口,在订阅通道接收返回数据"""
s.sendto(msg.encode(), (ip, int(port)))
return s.recv(1024).decode()
def send_cmd(ip, port, msg):
"""发送命令到对应的ip和端口,在随机通道(非订阅通道)接收返回数据"""
s_cmd.sendto(msg.encode(), (ip, int(port)))
return s_cmd.recv(1024).decode()
def talk_serv(pra):
""" 根据配置文件,自动从远端服务器注册,订阅消息 """
config = configparser.ConfigParser()
config.read('order.conf', encoding='UTF-8')
order_from = config.get('db', 'orderFrom')
data = order_from.split(',')
for d in data:
if pra == 'hello-connect':
print('--> '+check_data(send_msg(d.split(':')[0], d.split(':')[1], pra)), flush=True)
else:
print('--> '+check_data(send_cmd(d.split(':')[0], d.split(':')[1], pra)), flush=True)
def get_host_ip():
""" 查询返回本机ip地址 """
try:
s_ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_ip.connect(('8.8.8.8', 80))
ip = s_ip.getsockname()[0]
finally:
s_ip.close()
return ip
def check_data(d):
"""格式化各服务端的返回数据"""
if d.find('新发现故障') >= 0 or d.find('错误') >= 0:
winsound.PlaySound('err.wav', winsound.SND_FILENAME)
d = '\033[1;31;40m{0} \033[0m'.format(d)
elif d.find('故障持续') >= 0:
winsound.PlaySound('err.wav', winsound.SND_FILENAME)
d = '\033[1;33;40m{0} \033[0m'.format(d)
elif d.find('网络已恢复') >= 0:
winsound.PlaySound('shake.wav', winsound.SND_FILENAME)
d = '\033[1;32;40m{0} \033[0m'.format(d)
elif d.find('共') >= 0:
d = '\033[1;37;42m{0} \033[0m'.format(d)
else:
d = '\033[0;37m{0} \033[0m'.format(d)
return d
def init_server():
""" 初始化软件,一些初始设置及与服务器交互约定 """
global orderMode
while True:
data = input('Enter reg:')
if data == 'quit':
print('\r\n\033[0;31m开始接收数据.... \033[0m', flush=True)
break
elif data == 'orderMode=all':
orderMode = 'all'
print('订阅模式orderMode={0}'.format(orderMode), flush=True)
elif data == 'orderMode=err':
orderMode = 'err'
print('订阅模式orderMode={0}'.format(orderMode), flush=True)
elif len(data.split(':')) == 3:
data = data.split(':')
print(data[0], data[1], data[2])
print(send_msg(data[0], data[1], data[2]), flush=True)
else:
print('命令[{0}]错误,请检查。'.format(data), flush=True)
def run_order():
""" 开始执行订阅主功能 """
print('--> {0}:线程启动:开始执行订阅主功能,orderMode={1}'.format(time.strftime("%H:%M:%S"), orderMode), flush=True)
min_num = 0
max_num = 99999999
bar = ProgressBar(count=min_num, total=max_num, width=40)
animation = ['-', '\\', '|', '/']
count = 0
while True:
count += 1
data, address = s.recvfrom(1024) # 返回数据和客户端的地址与端口
d = check_data(data.decode())
if orderMode == 'err': # 只输出错误模式
if d.find('新发现故障') >= 0 or d.find('错误') >= 0 or d.find('异常') >= 0 or d.find('故障持续') >= 0 \
or d.find('网络已恢复') >= 0 or d.find('共:') >= 0 or d.find('- - -') >= 0:
bar.move()
bar.log('--> {0}'.format(d))
else:
print('\r{0}'.format(' '*100), end='') # 首先在当前行输出100个空格,清空内容,'\r'表示不换行回到最左边
print('\r{0}--> {1}'.format(animation[count % 4], d), end='') # 不换行
print('\r', end='', flush=True) # 将光标移动到左端,不换行,刷新输入
else:
bar.move()
bar.log('--> {0}'.format(d))
s.close()
def loop_check_heart(pra):
""" 定时检查服务是否正常 """
print('--> {0}:线程启动:定时任务自启动循环检查服务是否正常'.format(time.strftime("%H:%M:%S")), flush=True)
talk_serv(pra)
Timer(480, loop_check_heart, ('hello-heart',)).start()
def print_help():
welcome = '''欢迎使用网络监测程序订阅端,作者:wyw308 by/2018.11.18
python app.py --run app
Enter reg: remoteIp:port:hello-connect --order msg from remoteServer
Enter reg: remoteIp:port:hello-close --undo order from remoteServer
Enter reg: quit --run at recive msg mode
Enter reg: orderMode=all or err --recive mode,defalt is err mode
'''
print(welcome)
class ProgressBar:
# 进度条类
def __init__(self, count=0, total=0, width=50):
self.count = count
self.total = total
self.width = width
def move(self):
self.count += 1
def log(self, s):
sys.stdout.write(' ' * (self.width + 9) + '\r')
sys.stdout.flush()
sys.stdout.write(s + '\r\n')
progress = self.width * self.count / self.total
sys.stdout.write('+消息订阅[{0}]:{1:3}/{2:3}:'.format(time.strftime("%H:%M:%S"),self.count, self.total))
sys.stdout.write('#' * int(progress) + '-' * int((self.width - progress))+ '\r')
if progress == self.width:
sys.stdout.write('\n')
sys.stdout.flush()
def main():
os.system('') # 在执行完system()之后,win10转移序列都会生效,原因未知
print_help()
ip = get_host_ip() # 本机IP
# ip='10.17.90.79'
port = 6283 # 监听端口
s.bind((ip, port)) # 绑定 客户端口和地址
print('\033[0;32m Bind UDP on {0}:{1}...\033[0m'.format(ip, port), flush=True)
init_server()
talk_serv('hello-connect')
loop_check_heart('hello-heart')
t2 = threading.Thread(target=run_order)
t2.start()
t2.join()
if __name__ == '__main__':
main()