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