跳转至

网络工程师的python之路

最近有个需求,需要重复的对某几台防火墙进行某些操作,为了让不懂网络设备的同事也能一键操作,尝试了用python开发脚本,TODO:后续可以考虑弄个web界面,更友好。

一开始使用netmiko模块,1台设备执行1条命令需要20-30秒,N台设备*N,况且命令条数也是动态的,这样操作怕不是还没有手动快。同步不行就异步吧,后来研究了下netdev模块,功能实现后发现一个致命问题,~~截止目前为止netdev还不支持huawei的操作系统(已经向作者提交issue),没办法还是换回netmiko。~~

9.14更新,为netdev库增加了华为设备的支持,服务端用aiohttp,改为异步并发,速度快到不知哪去了(已经向作者提交PR)。后面有空再深入了解下asyncio~~

没法异步,要提高处理速度只有多线程,~~能异步当然还是异步快~~ 为了避免线程间数据同步以及复杂情况下线程锁的问题,最后用1个线程操作1台设备的方法,代码如下:

```python 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一遍似乎是比较通行的做法。