定时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:
知识兔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表示正在执行中
知识兔matplotlib折线图
x
知识兔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)
知识兔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:
知识兔模块的使用就如上介绍,下面放上在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
知识兔