前些天一個朋友有要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()