☰
网络设备自动配置实战:用Python与Netmiko批量管理交换机
2026/10/11 3:23:44 网站建设 项目流程

在机房泡过五年、手工刷过上千台设备配置之后,我第一次用脚本批量改完一百多台交换机的VLAN配置,整个人靠在椅背上愣了半天——手里那杯咖啡还没凉,活儿已经干完了。那种感觉,比在命令行里敲一千条interface GigabitEthernet0/1痛快得多。

如果你也是每天抱着Console线、对着SecureCRT窗口复制粘贴,或者还在用Excel整理设备清单然后一台一台手动登录,那我这篇内容就是给你写的。网络设备自动配置这件事,说穿了就是用Python代替你手指头干活,把“登录-敲命令-等回显-核对结果”这套流程固化成可重复执行的脚本。它能解决的问题很直接:批量变更快、配置统一、不用熬夜守变更窗口、出了事还能快速回滚。

这篇东西里我不会跟你掰扯太虚的概念,就是实打实讲讲怎么入手、用什么库、怎么写第一套能跑起来的脚本,以及我踩过的坑和总结出来的排查套路。不限厂商思路通用,只要你手上那些设备支持SSH,基本都能照这个路子走。

1. 为什么一定要做网络自动化配置

先把话说透:网络设备自动配置不是“为了酷”才搞的,它是在被现实反复捶打之后被逼出来的刚需。

1.1 手工配置的三大痛:慢、错、不可复制

先说慢。一次版本升级要改三十台核心设备,往少了说每条配置十行,三十台就是三百多行命令。你复制粘贴再快,一分钟顶多搞定两三台,还得每台盯着回显确认有没有报错。一晚上改完,人基本就废了。

再说错。人不是机器,复制粘贴最怕的是串行、漏行。我在现网里见过一次事故,工程师凌晨四点批量割接,其中一台设备把no shutdown漏掉了,业务早上七点才恢复。手工操作里这种低级错误根本防不住,因为人一旦疲劳或者赶时间,专注力就是会断崖式下降。

最坑的是不可复制。手工操作全凭脑子记,A同事的操作习惯和B同事完全不同。今天是你改了,下周他要去回滚,连你改了哪些配置都不知道。没有统一的脚本和标准化流程,操作记录靠聊天记录、靠回忆,出了问题根本没法追溯。

1.2 自动化能带来什么改变

自动化把这三件事一次性解决了。

速度上,脚本并发跑,三十台设备也许只需要一两分钟。精确性上,同样的模板往所有设备上推,每条命令都是预审核过的,不存在手滑漏掉的情况。可追溯性上,脚本本身就是变更记录,跑了哪台设备、发了什么命令、回显是什么,全都可以落盘存档,审计和回滚都方便。

说白了,自动配置的本质不是“把命令批量发出去”,而是把整个变更流程标准化、可编程化。你从“执行者”变成“流程设计者”,这才是网络工程师转型最有价值的那一步。

2. 工具选型:从Paramiko到Nornir,怎么选合适

很多新手一上来就问要学什么框架,我的建议是反着来:先搞清楚每个工具的定位,再根据你手头环境的复杂度选。

2.1 底层SSH库:Paramiko

Paramiko是Python实现的SSH协议库,相当于最底层的“万能钥匙”。它能帮你建立SSH连接、执行命令、拿回显,但什么都要自己来管:交互式shell要自己处理、设备分页要自己处理、命令超时要自己处理、回显清理要自己处理。

不是说它不好,它的价值在于“朴素可靠”。如果你的场景就是几台设备、几条命令,或者你想彻底搞清楚SSH连接和命令交互的底层逻辑,从Paramiko开始是收获最大的。

2.2 网络设备专属高级库:Netmiko

Netmiko是在Paramiko之上封装的专用库,初衷就是给网络工程师省事的。它内置了几十个厂商设备的命令交互规则,比如思科、华为、H3C、瞻博网络这些主流的,它都知道该怎么登录、该发什么去关分页、命令提示符长什么样、该怎么保证命令完整执行完。

这玩意儿给我最大的感觉就是“懂行”。它把网络工程师日常最麻烦的细节全处理掉了:自动等待命令执行完成的回显、自动关闭分页、自动处理二次认证(比如enable密码)、自动识别设备提示符。写起来几乎就是“连接-传命令-拿回显”三步。

2.3 结构化操作框架:NAPALM与Nornir

NAPALM的核心价值是“跨厂商一致性抽象”。它把设备操作抽象成获取配置、配置部署、回滚、获取facts这些标准动作。你在脚本里写同样的代码,底层不管接的是哪家厂商的设备,对外表现一致。

Nornir则是自动化编排框架,思路跟SaltStack有点像,但是专门针对网络设备的并行操作设计的。它自带并发、变量管理、任务追踪,适合大规模设备场景。你要是管几百台上千台设备,Nornir这套才是最趁手的。

2.4 选型建议:按场景对号入座

场景推荐方案理由
学习原理、教学演示Paramiko能看到交互全过程,底层细节尽在掌握
日常几十台设备批量操作Netmiko写起来最快,多厂商适配基本不用自己造轮子
多厂商混合、需要配置差异比对NAPALM统一数据模型,跨厂商逻辑一致
千台级规模、复杂编排Nornir + Netmiko并发能力强,任务编排清晰

我的个人习惯是:工作里90%的场景用Netmiko就够,偶尔碰多厂商标准化会用NAPALM,规模大到一定程度才上Nornir。这里边的原则就是——能用简单方案就别上复杂框架,少给自己找维护负担。

3. Netmiko实战:写一个能直接用的批量配置脚本

下面进入正题,我手把手拆一个基于Netmiko的批量配置脚本。所有代码我都实际跑过,你可以根据自己的环境改改设备IP、用户名密码就能用。

3.1 环境准备与依赖安装

建议用Python 3.8以上版本。先建虚拟环境,这是我一直以来的习惯,免得跟系统Python环境的包互相污染。

python3 -m venv netauto_env source netauto_env/bin/activate pip install netmiko

装完之后可以顺手确认一下版本,防止装到太老或太新的版本导致接口不一致。

pip show netmiko

3.2 编写第一个连接测试脚本

先别急着批量搞,先单台设备通一下。我把这个脚本命名为test_conn.py,作用是连到一台设备上,抓一下设备的系统信息,也就是大家常说的设备身份信息。

from netmiko import ConnectHandler device = { "device_type": "cisco_ios", # 按厂商型号填写,华为是huawei,H3C是hp_comware "host": "192.168.1.10", "username": "admin", "password": "your_password", "port": 22, "secret": "enable_secret", # enable密码,看设备是否需要 } conn = ConnectHandler(**device) output = conn.send_command("show version") print(output) conn.disconnect()

这里面最关键的就是device_type。Netmiko里这个字段决定了它用哪套交互逻辑,填错了会出怪问题。比如思科的IOS和IOS-XE虽然命令差不多,但设备类型如果选错,提示符匹配就会出问题。常见的映射如下:

设备厂商/平台device_type
思科 IOS / IOS-XEcisco_ios
思科 NX-OScisco_nxos
华为 VRPhuawei
H3C / 华三 Comwarehp_comware
瞻博网络 Junosjuniper
锐捷raisecom(部分版本)

send_command会等回显完全稳定之后才返回,这跟PDH层的send_command是两码事,日常用起来非常顺手。

3.3 批量下发配置:一次改动几十台设备

基础通了之后,来看批量场景。这里我用的是一个配置模板:给一批交换机的某一类接口统一配置描述和VLAN。

from netmiko import ConnectHandler from concurrent.futures import ThreadPoolExecutor import threading devices = [ { "device_type": "cisco_ios", "host": "192.168.1.10", "username": "admin", "password": "your_password", "secret": "enable_secret", }, { "device_type": "cisco_ios", "host": "192.168.1.11", "username": "admin", "password": "your_password", "secret": "enable_secret", }, # 更多设备按这个格式加就行,也可以直接从CSV读 ] config_commands = [ "interface GigabitEthernet0/1", "description To_Core_Switch", "switchport access vlan 100", "no shutdown", ] lock = threading.Lock() def push_config(device): try: conn = ConnectHandler(**device) conn.enable() # 进入特权模式 output = conn.send_config_set(config_commands) conn.save_config() # 保存配置 conn.disconnect() with lock: print(f"设备 {device['host']} 配置完成") except Exception as e: with lock: print(f"设备 {device['host']} 配置失败: {e}") with ThreadPoolExecutor(max_workers=10) as executor: for device in devices: executor.submit(push_config, device)

这段代码里有几个细节要特别注意。

conn.enable()是进特权模式的入口,如果设备不需要enable密码,也可以不调,但调了也无妨,最关键的是你的secret参数要配对,否则会卡在特权模式进不去。

send_config_set是专门用来一次性发送一组配置命令的。它还会自动进入配置模式、把命令逐条发送、最后退出配置模式,比你手动逐条发高效得多。

save_config是保存配置的操作,对应思科的write memory。这一步一定不能省,否则设备一重启,配置就全没了。

用ThreadPoolExecutor实现并发,这里max_workers=10意思是同时最多十台设备并行。这个值不建议设太大,一是设备侧自身的CPU处理能力有限,并发太高CPU飙升反而导致配置命令响应超时;二是一台台来太慢。我个人经验是,一般商用交换机并发在10到20之间效率最好,核心路由器要再保守一点。你要是有三百台设备要改,先拿三十台试并发15,观察一下延时和成功率再往大调。

我见过有人把并发设到50,结果一百台交换机CPU全部超过负载,SSH响应时间从几十毫秒变成十几秒,一堆连接超时。所以并发这东西,一定要实事求是地做压测。

3.4 读取设备清单:不把IP写死在脚本里

正经一点的场景里,设备清单都应该放在外部文件里。最常见的就是CSV,你平时用Excel管理设备清单的习惯可以直接迁移过来。

import csv from netmiko import ConnectHandler def load_devices_from_csv(filename): devices = [] with open(filename, mode="r", encoding="utf-8-sig") as f: reader = csv.DictReader(f) for row in reader: devices.append({ "device_type": row["device_type"], "host": row["ip"], "username": row["username"], "password": row["password"], "secret": row["secret"], }) return devices

CSV文件长这样:

device_type,ip,username,password,secret cisco_ios,192.168.1.10,admin,pass123,enable123 huawei,192.168.1.11,admin,pass456,enable456

你只需要维护好这个清单,脚本每次改配置之前从CSV里读就行。这样设备增删都只动文件不动脚本,非常省事。

3.5 自动保存配置回显:留痕才能无争议

前面我说了可追溯性,实现起来最简单的方式就是把每台设备的回显落到文件里。

import time timestamp = time.strftime("%Y%m%d_%H%M%S") for dev in devices: try: conn = ConnectHandler(**dev) conn.enable() output = conn.send_command("show running-config") conn.disconnect() filename = f"backup/{dev['host']}_{timestamp}.txt" with open(filename, "w") as f: f.write(output) print(f"{dev['host']} 备份完成 -> {filename}") except Exception as e: print(f"{dev['host']} 备份失败: {e}")

这就是配置备份脚本的雏形。定时跑一遍,配合cron或者Windows计划任务,你就拥有了一套最朴素的配置历史系统。哪台设备出了故障,翻出之前的配置一对比就知道被人动过哪里。

4. 从脚本到流程:配置变更的完整生命周期

脚本能连上设备、能发命令,这只是第一步。生产环境真正要的不是“一条命令”,而是一套安全的变更流程。你永远要假设“脚本会在最糟糕的时刻把设备改坏”。

4.1 变更前备份:不给自己留裸奔的机会

任何配置变更之前,必须先做完整配置备份。这属于底线纪律,任何生产环境操作都必须有完整的官方备份,否则变更失败想回滚都找不到依据。

上面那段备份脚本就是干这个的。变更当天、变更之前,先把所有涉及到的设备跑一遍备份。我见过太多人说“这次就改一条VLAN”就没备份,结果这条命令触发了解释器重启或者配置覆盖的问题,再想把旧配置捞回来已经晚了。

4.2 配置预检:用状态一致性检查脚本兜底

配置发完之后,还有一个关键步骤:验证配置到底生效了没有。总不能发完了就算完事,被改的设备状态是否符合预期,还是得眼见为实。

check_commands = [ "show vlan brief", "show interface status | include connected", ] for dev in devices: conn = ConnectHandler(**dev) for cmd in check_commands: output = conn.send_command(cmd) print(f"=== {dev['host']} - {cmd} ===") print(output) conn.disconnect()

这段是纯展示性质的。更靠谱的做法是在脚本里做关键字断言,比如检查VLAN 100是否存在、检查某个接口是否为connected状态。只有断言通过了才认为是变更成功,否则就纳入失败清单处理。这样人就不用满屏回显里自己找,机器直接告诉你结果。

if "100" in output: print("VLAN 100 配置存在,校验通过") else: print("VLAN 100 配置缺失,校验失败")

4.3 失败回滚:提前准备好“后悔药”

回滚是所有操作里最容易被忽略、出了事又最救命的一环。靠谱的思路是这样的:变更前把配置备份留好,变更后如果发现不符合预期,就把备份里的原始配置相关部分反推回去重新下发。

具体实现上,你有几个选择。最简单粗暴的就是把备份的配置整份刷回去,也就是把running-config整体恢复。这种方式适合配置量小的设备,命令多、耗时长、风险大,但简单。更精细一点的做法是只回滚变更涉及的部分,比如把接口下新增的VLAN配置删除,恢复成变更前的描述,这样做精度高、影响面小。

写回滚脚本的思路跟配置下发是一样的,只是把config_commands换成回滚命令,设备列表换成出问题的设备,执行后同样需要做校验确认回滚成功。我个人习惯是把回滚命令也模板化、预生成,千万别临时在现场凑命令,那种操作跟裸奔没区别。

5. 常见问题与排查技巧实录

自动化配置听着简单,实际跑起来问题一堆。我把这几年踩过的坑挑典型的说一说。

5.1 SSH连接报错:认证失败还是连接被拒?

最常见的报错有这么几类,我给你列个速查表:

错误现象可能原因排查方向
Authentication failed用户名密码错误先用PuTTY手工登录一遍
Connection refused设备SSH没开或端口不对检查端口和SSH配置
Timeout connecting设备到服务器的网络不通先ping一下设备地址
Connection unexpectedly closed设备SSH并发超限或会话数超限稍等重试,检查设备SSH并发配置
ValueError: Unknown device_typedevice_type字段拼错对照Netmiko支持的设备类型文档

排查思路就是:先用PuTTY或者系统自带SSH客户端直接手工连一遍,把人和脚本分离开定位问题。人手工能连上但脚本不行,那就是脚本参数问题;人手工都连不上,就别跟脚本较劲了,去查设备和网络。

5.2 设备回显乱码或者不完整

有时候在脚本里拿到的回显跟手工看到的完全对不上。原因大多是分页没有真正关掉,回显被截断在第一条--More--那里。或者就是设备返回了终端宽度相关格式控制符,导致内容乱了。

处理办法是:

  • 确认device_type选对,Netmiko会自动发送关闭分页的命令。
  • 手动SSH到设备上执行terminal length 0(思科)或screen-length 0 temporary(华为)确认能不能关闭分页。
  • 如果命令不同,可以在连接后用send_command_timing自定义关分页。

5.3 配置发到一半,脚本卡住不动

这个我遇到过好多次。最常见的原因是send_command等的是“命令执行完成的提示符”,而你的命令在某种状态下返回了一个不常见的提示符或者开启了交互式确认。比如思科某些接口配置时会问你“Do you want to continue? [confirm]”,脚本就会懵在那里。

解决办法有两个:

  • 在命令后面加上y或no来关闭交互确认,比如write memory改成write memory y。
  • 用send_command_timing,它会按固定时间间隔发送命令并读取回显,适合处理交互式流程。

5.4 并发太高导致设备SSH拒绝

前文我特意提过并发。这里多说一句:很多低端交换机的SSH管理并发默认只有几个,你要是一下子连十几个,后边的连接就会被设备拒之门外。表现就是前几个设备正常,后面全是Connection refused。

我的对策就是前面说的,控制max_workers在10以内,以及给脚本加个重试机制。

from tenacity import retry, stop_after_attempt, wait_fixed @retry(stop=stop_after_attempt(3), wait=wait_fixed(5)) def connect_with_retry(device): conn = ConnectHandler(**device) return conn

重试三次每次间隔五秒,能扛过大部分瞬时拒绝的问题。

5.5 配置文件里带特殊字符导致命令报错

比如你想把接口描述配成desc="To Server_1 (primary)",这里面的空格、括号在某些设备的CLI解析里都可能出问题。Netmiko发的命令本质是字符串,你字符串里有什么它就发什么,不会替你处理特殊字符。

解决办法是尽量不用特殊字符,或者把命令写成单引号包裹的字符串,自己确保目标设备能接受。这里没有统一的万能解,只能靠你对设备的了解。

6. 进阶方向:从脚本小子到流程建设者

脚本能跑、能批量配置,这只是自动化体系里最外层的一层皮。再往下走,你会发现真正花时间的不是写脚本,而是设计流程和规范。

6.1 配置模板化:一份模板适配一批设备

不同设备有不同的主机名、接口、IP,但同一批同角色的设备配置逻辑是高度相似的。这就是配置模板的用武之地。用Python的字符串模板功能就能实现简单的模板渲染。

from string import Template config_template = Template(""" hostname ${hostname} interface ${interface} description ${desc} switchport access vlan ${vlan} """) config = config_template.substitute( hostname="SW-ACC-01", interface="GigabitEthernet0/1", desc="To_Core", vlan=100 )

要做到这个程度,建议好好梳理一下你环境里的设备角色分类,比如接入层、汇聚层、核心层、WAN边缘、管理接口等。每类角色一套模板,再配上变量清单,配置的标准化程度会立刻上一个台阶。

6.2 密钥管理:脚本也要讲究安全性

拿生产环境的设备密码说,脚本里直接明文写密码肯定是不行的。你要么用环境变量,要么用外部密钥管理服务,要么至少用一个加密的配置文件。

最直接的方式是用操作系统环境变量:

import os device["password"] = os.environ.get("DEVICE_PASSWORD", "")

更规范一点的,可以接入密钥管理系统,从那里动态获取密码,用完后及时销毁。这是生产环境做网络自动化必须过的一关,别嫌麻烦,密码泄露一次你就不觉得麻烦了。

6.3 和现有系统打通:配置变更可视化

搞了脚本之后,下一个需求一定是“让我点个按钮就能跑”。这时候的思路就是用Web框架包一层管理界面,把设备清单、配置模板、变更记录全部收进去。你不需要搞多复杂,一个简单的Flask应用就够了:有人登录、选模板、选设备、点执行、看日志。

核心架构是这样的:Web界面接收请求,把设备清单和配置模板传给后台的自动化引擎,引擎执行后将结果日志入库。整个过程,脚本本身变成了服务的一部分,而不是孤零零的工具。

如果你已经用了配置管理平台,甚至可以不用自己开发,直接把Python脚本作为自定义模块集成进去。现阶段最重要的是把脚本的输入输出标准化:入参是设备列表和命令模板,出参是结果清单和日志文件,这样无论是人点按钮还是平台调接口,都能顺畅对接。

写在最后的一点体会

回头看我自己的经历,真正让自动化跑起来的转折点,不是学会了某个库的某个方法,而是改变了对“配置”这件事的看法——配置不再是“敲进设备里的命令”,而是“想要达成的目标状态加上一套可复现的执行流程”。

我最深的一个体会是:脚本跑通不算本事,脚本在无人值守的情况下稳定跑一百次不出事,那才叫真本事。而要做到这一步,靠的不是什么高大上的技巧,就是那些看上去很笨的功夫——备份、校验、重试、留痕,一个都不能少。

最后再分享一个小技巧:每次我跑批量配置脚本之前,都会挑一台非关键设备先跑一遍,确认回显和预期一致,再放开手脚跑剩余的全部设备。这个习惯帮我躲过好几次因为模板变量写错而引发的批量事故。你把这个习惯养成,就已经比大多数同行先迈了一步。

希望这篇东西能给你一点参考。下一步的建议很简单:别光看,找两台测试设备,装好Netmiko,把你第一个批量配置脚本跑起来。等你看到几十台设备的回显“唰唰唰”刷过屏幕的时候,你就明白自动化这件事为什么让人上瘾了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询