前些天一个朋友有要ping交易所前置以及绘制成折线图的需求,帮忙作了两天,感慨颇多,故写篇博客记录一下.node
首先,咱们的需求是,在window或者linux机器上定时执行ping + 网址 的语句,最终取到平均延迟,而后将这些延迟绘制成折线图.因此分析下来咱们须要如下几个模块来实现这个功能.python
定时功能:linux
datetime模块web
用window机器远程控制linux机器,并发送指令:编程
paramiko模块windows
绘制折线图:服务器
matplotlib模块并发
window机器上取本机的ping数据:app
subprocess模块
那么下面咱们逐一分析这些模块,以及怎么样使用,完成最后的需求.
相信咱们都使用过这个模块,那么咱们要实现天天定时来执行程序,就能够用如下方式来实现:
import datetime
import time
def main():
while True:
while True:
now = datetime.datetime.now()# 这里能够取到系统的当前时间
if now.hour == 6 and now.minute == 30:# 取当前时间的小时和分钟,这样天天到这个设定好的小时和分钟内的时候咱们就会跳出这个内循环,进入到外循环,从而执行主函数
# 固然设定时间咱们也能够设定秒,可是其实设定到秒的状况下有可能没法进入函数,时间过短系统没法断定
break
if now.hour == 9 and now.minute == 30:
break
if now.hour == 12 and now.minute == 30:
break
if now.hour == 14 and now.minute == 30:
break
time.sleep(20)
# 主函数
time.sleep(60)# 这里加入睡眠60秒是为了让主函数不至于在这一分钟内一直执行,仅执行一次就好
这个模块主要用于python调用系统的cmd窗口并返回结果,具体实现以下.
xxxxxxxxxx
# encoding=utf-8
import subprocess # 导入模块,没装的话本身去pip install subprocess
import sys
# 经常使用编码
GBK = 'gbk'
UTF8 = 'utf-8'
# 解码方式,通常 py 文件执行为utf-8 ,可是cmd 命令为 gbk
current_encoding = GBK
popen = subprocess.Popen(['ping', 'www.baidu.com'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=1)
# 重定向标准输出
while popen.poll() is None: # None表示正在执行中
r = popen.stdout.readline().decode(current_encoding)
sys.stdout.write(r) # 可修改输出方式,好比控制台、文件等
# 重定向错误输出
if popen.poll() != 0: # 不为0表示执行错误
err = popen.stderr.read().decode(current_encoding)
sys.stdout.write(err) # 可修改输出方式,好比控制台、文件等
x
'''
折线图绘制的时候主要碰到了下面几个问题:
1. 标签和折线的名称不能使用中文
解决:导入一个字体模块或者不用中文,用全拼或者英文
2. 绘图时候要控制图层的大小
解决: 在刚开始绘图的时候加入plt.figure(figsize=(10, 8)),能够调整图层的大小,后面的(10,8)实际大小是乘以100,也就是1000*800的图片大小
3. 最后保存图片的时候保存jpg格式出错
解决:须要额外装一个模块,语句 pip install pillow
'''
# 例程以下
from font_set import font_set# 这里我本身写了一个字体的模块,读者应该没有,能够忽略
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # SimHei是黑体的意思
x1 = ['06:00', '12:00', '18:00', '24:00']# 横轴
y1 = [4, 6, 8, 23]
z1 = [5, 5, 7, 15]
a1 = [2, 9, 10, 6]
# x = np.random.random_integers(1, 20, 10)
# # y = range(len(x))
fig = plt.figure(figsize=(10, 8))# 控制图层的大小
ax = fig.add_subplot(1, 1, 1)
ax.plot(x1, y1)
for x, y in zip(x1, y1):
plt.text(x, y + 0.3, '%.0f' % y, ha='center', va='bottom', fontsize=10.5)
ax.plot(x1, z1)
for x, y in zip(x1, z1):
plt.text(x, y + 0.3, '%.0f' % y, ha='center', va='bottom', fontsize=10.5)
ax.plot(x1, a1)
for x, y in zip(x1, a1):
plt.text(x, y + 0.3, '%.0f' % y, ha='center', va='bottom', fontsize=10.5)
plt.xlabel(u'时间', FontProperties=font_set)
plt.ylabel(u'延迟', FontProperties=font_set)
plt.title(u"各交易所交易延时", FontProperties=font_set)
plt.legend([u"中金所", u"上期所", u"大商所"], prop=font_set)
plt.savefig("1.jpg")# 这里要注意,要先保存再show,若是先show了保存图片就会是空白
plt.show()
x
'''
paramiko模块主要做用是用python来远程链接服务器,发送请求以及取数据,因为使用的是python这样的可以跨平台运行的语言,因此全部python支持的平台,如Linux, Solaris, BSD, MacOS X, Windows等,paramiko均可以支持,所以,若是须要使用SSH从一个平台链接到另一个平台,进行一系列的操做时,paramiko是最佳工具之一。
'''
class Ping_jifang:# 定义一个ping的类
def __init__(self, host_ip, username, password, command, port=22):
self.ssh = paramiko.SSHClient()
self.host_ip = host_ip
self.username = username
self.password = password
self.command = command
self.port = port
def ssh_jifang(self):
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.ssh.connect(self.host_ip, self.port, self.username, self.password, timeout=8)
return True
except Exception as fail:
return False
def exec_ssh_command(self):
stdin, stdout, stderr = self.ssh.exec_command(self.command)
result_all = stdout if stdout else stderr
# print(result_all.readlines())
return result_all.readline()
# return stdout
# print(self.command)
# result_all = os.popen(self.command)
# return result_all
def logout(self):
self.ssh.close()
def main():
print('进入主函数')
ip_dit = {
"yidong1": {
"info": ["ip地址", "用户名", "密码"]
},
"yidong2": {
"info": ["ip地址", "用户名", "密码"]
},
"shuxun": {
"info": ["ip地址", "用户名", "密码"]
},
"languang": {
"info": ["ip地址", "用户名", "密码"]
}
}
# 这个语句就是咱们用当前操做机来发送给linux机器的语句
command_ping = "ping 114.114.114.114 -c 100 -i 0.001 -f | grep 'rtt' | awk -F '[ =/]+' '{print $7}'"
for i in ip_dit:
client_ping = Ping_jifang(ip_dit[i]["info"][0], ip_dit[i]["info"][1], ip_dit[i]["info"][2], command_ping)
if client_ping.ssh_jifang():
result = client_ping.exec_ssh_command()
result = eval(result[:-2])# 由于绘图须要列表,列表内要是int或者float数据,因此这里咱们切割掉\n,而后用eval去掉引号,从而使列表内是符合要求的能够绘图的数据
# print(i)
# print(type(a),yidong2.append(a),yidong2)
if i == "yidong1":
yidong1.append(result)
elif i == "yidong2":
yidong2.append(result)
elif i == "shuxun":
shuxun.append(result)
elif i == "languang":
languang.append(result)
else:
pass
client_ping.logout()
print(yidong1)
print(yidong2)
print(shuxun)
print(languang)
模块的使用就如上介绍,下面放上在linux和window机器上分别可使用的完整程序.
xxxxxxxxxx
'''
此程序是取本机(windows)对于其余网址的ping延迟
'''
import subprocess, sys, time, re, datetime
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from pylab import mpl
from threading import Thread
mpl.rcParams['font.sans-serif'] = ['SimHei'] # SimHei是黑体的意思
plt.style.use('ggplot')
np.random.seed(1)
# 字体要导一下,还有别的导字体方法,这只是一种
font_set = FontProperties(fname=r"D:\\msyh.ttc", size=12)
count = 0
# %Y-%m-%d
def delay(host):
popen = subprocess.Popen(['ping', host],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=1)
while popen.poll() is None:
r = popen.stdout.readline().decode('gbk')
# sys.stdout.write(r)
# 这里是取字段的功能,linux里面应该是按avg取,windows里面是按汉字'平均'取得
res = re.findall(r'平均 = (.*?)ms', r)
if res:
return res[0]
if popen.poll() != 0:
err = popen.stderr.read()
sys.stdout.write(err)
def run():
print('进入程序主体')
global time_x
time_x.append(time_now)
res1 = delay('www.qq.com')
global lis1
lis1.append(eval(res1))
res2 = delay('www.baidu.com')
global lis2
lis2.append(eval(res2))
res3 = delay('www.jianshu.com')
global lis3
lis3.append(eval(res3))
res4 = delay('www.runoob.com')
global lis4
lis4.append(eval(res4))
print(len(lis1))
print(lis1)
time.sleep(1)
if len(lis1) == 4: # 当取到四个延迟数据,也就是一天过去的时候,会生成折线图
print('进入绘图函数')
plt.figure(figsize=(10, 8)) # 调整图层大小
plt.plot(time_x, lis1, marker='o', mec='b', mfc='w', label=u'QQ')
for x, y in zip(time_x, lis1):
plt.text(x, y + 0.3, '%.0f' % y, ha='center', va='bottom', fontsize=10.5)
plt.plot(time_x, lis2, marker='v', mec='g', mfc='w', label=u'百度')
plt.plot(time_x, lis3, marker='^', mec='r', mfc='w', label=u'简书')
plt.plot(time_x, lis4, marker='s', mec='y', mfc='w', label=u'菜鸟编程')
plt.plot([0, 15, 30, 45], "rd")
plt.margins(0)
plt.subplots_adjust(bottom=0.10)
plt.xlabel(u'时间', FontProperties=font_set) # X轴标签
plt.ylabel(u'延迟ms', FontProperties=font_set) # Y轴标签
plt.title(u"各交易所交易延时", FontProperties=font_set)
plt.grid(True)
plt.legend(loc=0)
global count
count += 1
plt.tight_layout()
plt.savefig(f"{date}-{count}.jpg") # 保存的文件名
# plt.show()
plt.close() # 这里要注意,必定要关闭当前图层,否则以后画出来的图会和以前的图合并出现
print('重置列表')
time_x.clear()
lis1.clear()
lis2.clear()
lis3.clear()
lis4.clear()
if __name__ == '__main__':
# 设定的开始时间,即第一次等于这个时间的时候开始进入程序,获得第一个延迟数据,以后能够一直不关,这个时间会一直保持增加
sched_Timer = datetime.datetime(2019, 9, 27, 10, 38, 00)
lis1 = list()
lis2 = list()
lis3 = list()
lis4 = list()
time_x = list()
while True:
date = time.strftime('%Y-%m-%d', time.localtime(time.time()))
time_now = time.strftime('%H:%M:%S', time.localtime(time.time()))
now = datetime.datetime.now() # 取到当前系统的时间
# if sched_Timer < now < (sched_Timer + datetime.timedelta(seconds=1)):
if 1 == 1:
t1 = Thread(target=run) # 子线程
t1.start()
t1.join()
# 这里是延迟时间,即设定为hour=6就是六个小时ping一次数据,minutes=1就是一分钟ping一次,累计四次才会生成一个图片
sched_Timer = sched_Timer + datetime.timedelta(minutes=1)
x
'''
此程序是本机经过远程linux机器来取不一样linux机器的ping的延迟
'''
import paramiko
import time
import datetime
import matplotlib.pyplot as plt
# font_set = FontProperties(fname=r"D:\\msyh.ttc", size=12)
# font_set = FontProperties(fname='utf-8', size=12)
class Ping_jifang:
def __init__(self, host_ip, username, password, command, port=22):
self.ssh = paramiko.SSHClient()
self.host_ip = host_ip
self.username = username
self.password = password
self.command = command
self.port = port
def ssh_jifang(self):
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.ssh.connect(self.host_ip, self.port, self.username, self.password, timeout=8)
return True
except Exception as fail:
return False
def exec_ssh_command(self):
stdin, stdout, stderr = self.ssh.exec_command(self.command)
result_all = stdout if stdout else stderr
# print(result_all.readlines())
return result_all.readline()
# return stdout
# print(self.command)
# result_all = os.popen(self.command)
# return result_all
def logout(self):
self.ssh.close()
def main():
print('进入主函数')
ip_dit = {
"yidong1": {
"info": ["10.0.0.99", "root", "1"]
},
"yidong2": {
"info": ["10.221.1.190", "root", "htqh@2019"]
},
"shuxun": {
"info": ["10.225.1.94", "root", "123456"]
},
"languang": {
"info": ["10.121.137.58", "root", "htqh@1234"]
}
}
command_ping = "ping 114.114.114.114 -c 100 -i 0.001 -f | grep 'rtt' | awk -F '[ =/]+' '{print $7}'"
for i in ip_dit:
client_ping = Ping_jifang(ip_dit[i]["info"][0], ip_dit[i]["info"][1], ip_dit[i]["info"][2], command_ping)
if client_ping.ssh_jifang():
result = client_ping.exec_ssh_command()
result = eval(result[:-2])
# print(i)
# print(type(a),yidong2.append(a),yidong2)
if i == "yidong1":
yidong1.append(result)
elif i == "yidong2":
yidong2.append(result)
elif i == "shuxun":
shuxun.append(result)
elif i == "languang":
languang.append(result)
else:
pass
client_ping.logout()
print(yidong1)
print(yidong2)
print(shuxun)
print(languang)
# 绘图函数
if len(yidong2) == 4: # 当取到四个延迟数据,也就是一天过去的时候,会生成折线图
plt.figure(figsize=(10, 8)) # 调整图层大小
time_x = ['06:00', '09:00', '12:00', '15:00']
date = time.strftime('%Y-%m-%d', time.localtime(time.time()))
print('进入绘图函数')
# plt.plot(time_x, yidong1, marker='o', mec='b', mfc='w', label=u'QQ')
for x, y in zip(time_x, yidong2):
plt.text(x, y + 0.3, '%.0f' % y, ha='center', va='bottom', fontsize=10.5)
plt.plot(time_x, yidong2, marker='v', mec='g', mfc='w', label=u'shuxun')
plt.plot(time_x, shuxun, marker='^', mec='r', mfc='w', label=u'zhongjinsuo')
plt.plot(time_x, languang, marker='s', mec='y', mfc='w', label=u'yidong')
plt.ylim(0, 20) # 纵坐标范围
y = range(0, 20, 1)
plt.yticks(y) # 纵坐标刻度
plt.margins(0)
plt.subplots_adjust(bottom=0.10)
plt.xlabel(u'time') # X轴标签
plt.ylabel(u'ms') # Y轴标签
plt.title(u"timedelate")
plt.legend(loc=0)
global count
count += 1
plt.tight_layout()
plt.savefig(f"{date}-{count}.jpg") # 保存的文件名
# plt.show()
plt.close() # 这里要注意,必定要关闭当前图层,否则以后画出来的图会和以前的图合并出现
print('重置列表')
time_x.clear()
yidong1.clear()
yidong2.clear()
shuxun.clear()
languang.clear()
if __name__ == "__main__":
yidong1 = []
yidong2 = []
shuxun = []
languang = []
count = 0
while True:
while True:
now = datetime.datetime.now()
print(f'\r当前时间:{now}', end='')
if now.hour == 16 and now.minute == 1:
break
if now.hour == 16 and now.minute == 15:
break
if now.hour == 16 and now.minute == 16:
break
if now.hour == 16 and now.minute == 17:
break
time.sleep(1)
time.sleep(61)
main()