最近有个需求,需要重复的对某几台防火墙进行某些操作,为了让不懂网络设备的同事也能一键操作,尝试了用python开发脚本,TODO:后续可以考虑弄个web界面,更友好。
一开始使用netmiko模块,1台设备执行1条命令需要20-30秒,N台设备*N,况且命令条数也是动态的,这样操作怕不是还没有手动快。同步不行就异步吧,后来研究了下netdev模块,功能实现后发现一个致命问题,截止目前为止netdev还不支持huawei的操作系统(已经向作者提交issue),没办法还是换回netmiko。
9.14更新,为netdev库增加了华为设备的支持,服务端用aiohttp,改为异步并发,速度快到不知哪去了(已经向作者提交PR)。后面有空再深入了解下asyncio~~
没法异步,要提高处理速度只有多线程,能异步当然还是异步快 为了避免线程间数据同步以及复杂情况下线程锁的问题,最后用1个线程操作1台设备的方法,代码如下:
from netmiko import ConnectHandler
import time
from queue import Queue
import threading
def fengdu_hw(device,output_q):
try:
net_connect = ConnectHandler(**device)
file = open('./ip_list.txt')
for ip in file.readlines():
ip = ip.strip()
#要配置的命令
config_commands = ['ip address-set fengdu_20200821_1',
'address '+ip+' 0']
#提交要配置的命令,input为提交的真实内容
input = net_connect.send_config_set(config_commands)
except:
print(f"{ip} 操作失败,请检查!")
else:
print(f"{ip} 操作成功!")
return
def fengdu_h3c(device,output_q):
try:
net_connect = ConnectHandler(**device)
file = open('./ip_list.txt')
for ip in file.readlines():
ip = ip.strip()
#要配置的命令
config_commands = ['object-group ip address fengdu_20200821_1',
'network host address '+ip]
#提交要配置的命令,input为提交的真实内容
input = net_connect.send_config_set(config_commands)
except:
print(f"{ip} 操作失败,请检查!")
else:
print(f"{ip} 操作成功!")
return
hw1 = {
'device_type':'huawei',
'host':'X.X.X.X',
'username':'xxxxx',
'password':'xxxxx'
}
hw2 = {
'device_type':'huawei',
'host':'X.X.X.X',
'username':'xxxxx',
'password':'xxxxx'
}
hw3 = {
'device_type':'huawei',
'host':'X.X.X.X',
'username':'xxxxx',
'password':'xxxxx'
}
h3c = {
'device_type':'hp_comware',
'host':'X.X.X.X',
'username':'xxxxx',
'password':'xxxxx'
}
print(f"操作于 {time.strftime('%X')} 开始执行\n")
t1 = threading.Thread(target=fengdu_hw, args=(hw1,Queue()))
t2 = threading.Thread(target=fengdu_hw, args=(hw2,Queue()))
t3 = threading.Thread(target=fengdu_hw, args=(hw3,Queue()))
t4 = threading.Thread(target=fengdu_h3c, args=(h3c,Queue()))
threads = [t1,t2,t3,t4]
for t in threads:
t.start()
for t in threads:
t.join()
print(f"\n操作于 {time.strftime('%X')} 执行结束")
join
方法是个很tricky的东西,至今还不是很清楚地懂这是个什么玩意儿。join([timeout])方法阻塞了主线程,直到调用此方法的子线程完成之后主线程才继续往下运行。(之前我糊里糊涂地把join就紧紧接在start后面写了,如果这么写了的话那么多线程在速度上就毫无优势,和单线程一样了= =)。而像上面这个示例一样,先一个遍历把所有线程都启动起来,再用一个遍历把所有线程都join一遍似乎是比较通行的做法。