ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python+SSH网络设备自动化:批量备份与配置下发实战

Python+SSH网络设备自动化:批量备份与配置下发实战 简介一份以Python与SSH协议为核心、面向网络自动化运维场景的毕业设计文档资源适合具备一定Python编程基础的网络运维人员、IT自动化工程师及计算机相关专业学生。文档从传统人工运维效率低、误操作率高的痛点切入系统分析自动化运维的定义与分类明确系统查询、自动配置、自动检查与自动保存四大功能指标基于华为eNSP模拟器搭建网络拓扑借助FreeSSHd建立传输通道并使用paramiko、re、time等Python模块实现远程连接、命令执行、信息采集与配置管理。具体包括设备版本、接口状态、IP地址、内存使用等信息查询以及用户配置、访问控制和配置文件备份等自动化操作可显著减少重复劳动并提升运维准确性。资源包仅含1个docx文档大小1.89MB内附完整程序代码、实验拓扑说明及功能测试结果可支撑读者从环境搭建、代码实现到结果验证的完整实践路径。已有107人学习下载对入门网络自动化、深入理解SSH协议交互与正则分析设备输出均有较高参考价值。 凌晨两点半我刚把第47台交换机的配置粘贴完手已经快抽筋了。原因很简单全网57台设备要统一加一行VRRP优先级命令没有现成的网管平台只能一台台登录、粘贴、确认。第二天我花一上午用Python把整个流程重写掉之后再做类似变更最多跑一遍脚本、喝杯咖啡的工夫。这就是网络运维里最典型的自动化切入点——利用SSH协议管理网络设备把重复、机械、高风险的日常操作交给代码去执行。这篇内容不是讲那些动辄上千万的商用网管平台而是从零开始用Python生态里最常用的几个库把“通过SSH批量登录设备、执行命令、收配置、下发配置”这件事做扎实。无论你是在管小机房的几十台设备还是在做几百台设备的日常巡检这套思路都能直接落地。我会把选型理由、连接参数、实战脚本、回滚设计、还有我踩过的坑一次讲清楚尽量让看过的人能照着写写完能直接上生产。1. 为什么网络设备自动化首选Python加SSH1.1 从“人肉运维”到脚本运维的临界点很多网工朋友最开始对自动化是无感的觉得设备量不大脚本还要调试不如手敲来得快。这个想法在设备少于十几台的时候确实成立但一旦越过某个临界点手敲就开始失控。我自己体会最深的不是“慢”而是“一致性”——你说这57台设备都加了VRRP优先级谁能证明每台都加上了复制粘贴漏了一台或者某台设备命令语法略有差异当时根本发现不了等到故障时才追悔莫及。当设备量超过二三十台或者变更频率超过一周一次自动化的价值已经不是“省时间”而是“确定性”。代码执行同样的命令序列只要逻辑正确、异常捕获到位结果就是一致的并且日志里清清楚楚记录着哪台成功、哪台失败。这种确定性是任何手工操作都给不了的。1.2 SSH在设备管理方式里的统治地位网络设备的管理协议其实有很多种telnet、SNMP、SSH、NETCONF、RESTCONF、甚至串口console线。但你要真在生产环境里做批量操作SSH协议几乎是唯一“通吃”的选择——telnet是明文传输密码直接裸奔现在等保和合规根本过不去SNMP更适合监控采集做配置写入非常别扭NETCONF/RESTCONF虽然现代化但很多存量设备不支持尤其是老旧的华为、思科机型接口实现还不统一。SSH的优势在于它足够通用、足够安全而且所有网络设备厂商都支持。更关键的是运维人员的操作习惯就是“命令行登录设备再敲命令”SSH恰好是这种交互方式的安全承载。Python生态里有非常成熟的SSH库我们不需要自己实现SSH协议只需要关注“怎么和设备交互”这件事。还有一个隐形优势SSH协议走的是TCP 22端口绝大多数网络环境对它天然放通不需要为自动化脚本额外调整防火墙策略。这一点在跨网络区域做自动化时特别省心。1.3 Python生态为什么最适合这个场景说实话用其他语言也能做设备自动化Go、Java都可以但Python在这件事上有两个碾压级优势一是库的成熟度Paramiko、Netmiko、Nornir这些库就是为网络设备交互而生的把底层SSH握手、认证、命令回显等待全封装好了二是上手门槛运维人员本身的强项在网络而不是软件开发Python语法足够简单写个自动化脚本不需要系统学过编程边查边写就能跑起来。所以我一直建议刚接触自动化的网工朋友第一门语言不用纠结直接学Python第一个自动化场景就从SSH登录设备开始。这个路径短平快正反馈来得特别快很容易建立信心。2. Netmiko与Paramiko的选型思路别一上来就写socket2.1 两个库到底是什么关系很多教程一上来就让人用Paramiko写SSH客户端理由是“底层、灵活”。但对网络设备运维来说直接操作Paramiko其实是给自己找麻烦。Paramiko是一个Python实现的SSH协议库它负责建立加密连接、执行远程命令但“网络设备”这件事它一概不知——它不知道思科的设备需要自动进入enable模式不知道华为设备默认开启分页输出也不知道命令敲太快设备会丢字符。Netmiko是建立在Paramiko之上的网络设备自动化库它的作者Kirk Byers本身就是网络工程师所以里面所有的封装逻辑都带着网工思维。它会自动处理设备类型差异比如思科自动进入特权模式、华为自动处理分页、命令回显等待时间自适应等。相当于把Paramiko这块生铁锻造成了趁手的工具。2.2 选型对比什么场景用什么库这里直接给一张我在实际项目里总结的对比表方便你按场景选型对比项ParamikoNetmiko封装层级基础SSH协议封装基于Paramiko的二次封装设备类型适配无需自己处理交互差异内置几十种设备类型分页处理手动执行terminal length 0自动处理enable模式手动判断和切换配置项自动处理命令回显等待需要自己sleep和轮询基于设备提示符智能判断学习成本中等较低灵活性高中等从表里能看出如果你的目标就是“批量登录网络设备执行命令”Netmiko是省力且稳妥的选择。它把网络设备交互中最容易出错的几个环节分页、等待、特权模式都处理掉了能让你把精力聚焦在业务流程上而不是和SSH协议死磕。什么情况下需要用Paramiko我遇到过的场景是接入一些非标准设备比如某厂家的AP管理系统、自定义串口服务器这些设备不支持Netmiko的device_type交互逻辑也别扭这时候直接用Paramiko自己控制收发更靠谱。还有就是要做底层协议学习或者深度定制时Paramiko是更好的基础。2.3 我的选择习惯与理由我的做法是“默认Netmiko特殊情况再降级Paramiko”。原因很简单Netmiko已经帮我覆盖了95%的网络设备场景包括思科IOS、华为VRP、H3C Comware、锐捷、Juniper等。而且Netmiko的异常体系很完整比如NetmikoTimeoutException、NetmikoAuthenticationException异常类型明确写出来的代码可靠性更高后续做批量操作时也方便统一捕获处理。如果你之前完全没接触过这两个库听我一句劝不要从Paramiko开始学直接从Netmiko上手等你把设备批量管理做起来了再回头研究底层实现也不迟。3. 环境准备与连接参数设备连不上九成是这里的问题3.1 环境搭建其实就三步环境准备并不复杂核心就三步装Python、装Netmiko库、确认网络能通到设备。Python版本建议3.8以上太老的版本对第三方库的支持会越来越差。Netmiko安装直接pip就好pip install netmiko如果你在中国大陆网络环境pip源可以换成国内镜像速度会快很多pip install netmiko -i https://pypi.tuna.tsinghua.edu.cn/simple装完之后验证一下python -c import netmiko; print(netmiko.__version__)能打印出版本号就说明环境OK了。这里有个小建议不要图方便在系统全局环境里装Python库建议用venv或者conda建一个独立环境否则哪天你升级了系统自带的Python库依赖全乱了排查起来很头大。我自己就吃过这个亏后来所有自动化项目都统一用虚拟环境管理。3.2 连接参数详解每个字段都有讲究用Netmiko连接设备时核心就是构造一个连接参数字典然后实例化ConnectHandler。直接看一个连接华为设备的例子from netmiko import ConnectHandler device { device_type: huawei, host: 192.168.10.1, username: netadmin, password: Admin12345, port: 22, timeout: 30, conn_timeout: 30, } conn ConnectHandler(**device) output conn.send_command(display version) print(output) conn.disconnect()这里面的参数有几个值得细说device_type这个字段千万别随便填填错了连接就直接失败。常见的取值包括cisco_ios思科IOS交换机/路由器、huawei华为VRP系统、hp_comwareH3C/华三、arista_eos等。Netmiko内置了完整的设备类型清单不确定的话可以导入netmiko后打印netmiko.platforms查看。timeout这是SSH连接的会话超时时间单位秒。如果你的设备响应慢建议设置30秒以上否则网络抖动一下连接就断了。conn_timeout指SSH建连阶段的超时时间第一次连设备时TCP握手SSH密钥交换如果超过这个时间就会连接失败通常15到30秒是合理的。port绝大多数设备SSH服务在22端口但有些安全加固过的环境会改成别的端口按环境设置即可。3.3 认证方式与安全建议Netmiko默认支持用户名密码认证这是最简单也最常见的做法。生产环境我强烈建议用SSH密钥认证这样密码不会出现在脚本里也方便后续做审计。Netmiko支持use_keysTrue加key_file参数指定私钥路径。但需要注意一点很多网络设备特别是华为老版本的SSH密钥认证实现比较特殊和设备类型有关。我在实际项目里遇到过几次“密钥配置了但就是登录不了”的情况最后都是退回密码认证解决。如果你用密钥认证失败不要死磕先用密码跑通流程再回头解决认证问题。另外脚本中涉及明文密码时不要硬编码在代码里建议从环境变量或独立的配置文件读取配合作业平台注入这样可以避免密码泄露到代码仓库里。这个习惯早养成早好我见过太多人把密码提交到Git仓库然后被全网扫面的案例了。3.4 连接不上时的排查顺序连接不上设备是最常见的问题我的排查顺序是先ping设备确认网络通不通再telnet到22端口确认SSH服务是否正常然后单独用命令行SSH客户端连一次确认账号密码可用最后才怀疑脚本参数。这样一步步下来80%的问题都能定位到。如果你发现命令行能连上但Netmiko连不上重点检查device_type是否匹配设备系统这个坑我踩过不下五次。4. 第一个能上生产的脚本批量备份设备配置4.1 为什么我建议第一件事做配置备份很多人学了Netmiko之后第一件事就想去写配置下发我建议先等等。配置下发风险高一旦逻辑有bug可能就是全网故障。而配置备份是纯读操作风险几乎为零但价值却非常大——有了历史配置你做变更回滚、故障排查、合规审计都有了依据。所以我带新人写自动化时第一个实战项目永远是“批量备份全网设备配置”。备份的另一个好处是能让你提前暴露连接参数、设备类型、超时设置这些问题。如果备份脚本能在几百台设备上稳定跑一遍你对这套代码的信任度就有了再做配置下发心里也有底。4.2 从单机备份到批量备份的完整实现先看单机备份的核心代码还是以华为设备为例from netmiko import ConnectHandler import datetime def backup_single_device(device_info, backup_dirbackup): device { device_type: device_info.get(device_type, huawei), host: device_info[host], username: device_info[username], password: device_info[password], port: device_info.get(port, 22), timeout: 30, conn_timeout: 30, } conn ConnectHandler(**device) output conn.send_command(display current-configuration) filename f{backup_dir}/{device_info[host]}_{datetime.datetime.now().strftime(%Y%m%d_%H%M%S)}.cfg with open(filename, w, encodingutf-8) as f: f.write(output) conn.disconnect() return filename这段代码逻辑很简单但有几个细节是经验所在。首先华为设备备配置用的是display current-configuration思科设备则是show running-config不同设备类型的采集命令不一样所以device_type选对之后采集命令也要对应切换。其次保存文件用时间戳命名避免覆盖历史记录。我习惯的文件命名格式是IP_日期_时间.cfg这样就算一天备份多次也不会把之前的版本冲掉。批量备份就是在这个基础上加一个读取设备清单的循环import csv import os import logging logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) def batch_backup(device_filedevices.csv): os.makedirs(backup, exist_okTrue) with open(device_file, r) as f: reader csv.DictReader(f) devices list(reader) for item in devices: try: filename backup_single_device(item) logging.info(f{item[host]} 备份成功: {filename}) except Exception as e: logging.error(f{item[host]} 备份失败: {e})devices.csv的内容大概长这样device_type,host,username,password,port huawei,192.168.10.1,netadmin,Admin12345,22 cisco_ios,192.168.10.2,netadmin,Admin12345,22 huawei,192.168.10.3,netadmin,Admin12345,22这是个非常朴素的“遍历设备执行任务”结构后面你想加巡检、加配置下发都是在这个骨架上演进。这里我用的是循环串行执行设备量大的时候会慢后面讲并发时再优化。4.3 备份结果的校验比备份本身更重要脚本跑完不代表备份就成功了有一个问题是所有备份脚本都会遇到的设备回显可能不完整。比如设备配置太长分页没有完全关闭那么send_command返回的内容就是截断的你这边存了一个残缺的配置文件还以为成功了。怎么校验我的经验是多管齐下第一在发送采集命令前先执行screen-length 0 temporary华为或terminal length 0思科关闭分页第二检查输出长度如果配置明显过短比如小于几百行要标记为可疑第三对比文件大小正常情况下同型号设备的配置量级差不多如果某台设备文件大小和同类设备差异巨大多半是采集出了问题。Netmiko的send_command其实自带一些等待逻辑但对于分页这种问题还是要在协议层面处理干净才安心。我看过太多备份脚本跑得很欢一检查发现三分之一设备备份的配置是残缺的这个问题务必重视。5. 配置下发与回滚自动化变更的安全底线5.1 下发命令和读命令不是一回事读命令失败最多是拿不到数据写命令失败可能就是一次全网事故。所有刚接触设备自动化的朋友必须从第一天就建立这个意识配置下发代码的错误处理标准远比备份代码要高得多。用Netmiko下发配置的核心方法是send_config_set它的特点是进入配置模式、逐条执行命令、然后退出配置模式。看一个给华为设备批量修改接口描述的例子from netmiko import ConnectHandler device { device_type: huawei, host: 192.168.10.1, username: netadmin, password: Admin12345, timeout: 30, conn_timeout: 30, } conn ConnectHandler(**device) config_commands [ system-view, interface GigabitEthernet0/0/1, description Uplink-to-Core-01, return, ] output conn.send_config_set(config_commands) print(output) conn.disconnect()注意这里的命令列表可以包含进入系统视图、进入接口视图、修改参数、退出等完整命令序列。send_config_set会自动处理进入和退出配置模式实际上如果你是给思科设备下发命令通常连configure terminal都不用手写Netmiko会按设备类型自动处理。但为了可读性和可控性我习惯把命令完整写出来这样不同设备厂商切换时也更容易排查问题。5.2 变更前备份、变更中校验、变更后确认我给自己定的铁律是任何配置变更必须三步走。第一步脚本自动对目标设备做一次配置备份这个备份要在变更前的几分钟内完成确保回滚基线是最新状态第二步下发配置后立即执行验证命令采集配置是否生效、设备状态是否正常第三步上报全部回显结果由人来最终确认变更是否成功。看一个完整的最小实现def change_device_config(device_info, config_commands): conn ConnectHandler(**device_info) # 第一步变更前备份 before conn.send_command(display current-configuration) backup_file save_to_file(device_info[host], before, before_change) logging.info(f变更前备份已保存: {backup_file}) # 第二步下发配置 output conn.send_config_set(config_commands) logging.info(f配置下发回显: {output}) # 第三步验证配置是否生效 verify_commands [display this, dis ip interface brief] for vcmd in verify_commands: vresult conn.send_command(vcmd) logging.info(f验证命令 {vcmd} 回显: {vresult}) conn.disconnect()这个流程看起来简单但它确保了每一台设备在变更后都有据可查。如果哪台设备验证失败脚本会通过日志记录下来你拿着设备IP直接去看就行。5.3 回滚设计比变更本身更重要的兜底方案没人希望用到回滚但用到的时候如果发现回滚机制是坏的那才是真正的灾难。回滚的设计原则特别简单变更前存储完整配置快照变更失败时用快照恢复。存储快照的方式有两种一是把配置文本保存到本地文件二是直接利用设备的save命令让设备自己保存一份当前配置。具体到华为设备回滚命令就是先把备份配置文件上传到设备然后用配置替换的方式恢复。如果你的设备数不多最简单的回滚逻辑就是重新登录设备执行undo命令把变更撤销或者直接恢复之前保存的配置。但要注意设备配置有些是增量的有些是覆盖式的不是所有undo都能精确还原所以最稳妥的回滚还是整机配置恢复。Netmiko本身不提供配置回滚功能除非用Netmiko的send_config_from_file把备份配置重新下发但你可以把它封装在自己的脚本里。我的建议是写自动化配置变更脚本的时候必须同时写好回滚脚本并且在下发前做一次演练确认回滚脚本能在真实设备上跑通。两条腿走路才稳当。5.4 全量配置比对无人值班的最后一道闸还有一个进阶操作变更完成后不要让设备留在“未知状态”要拿变更后配置和期望配置做差异比对。实际项目中我常把设备最终配置抓下来和理想配置模板做逐行diff只有diff结果符合预期这次变更才算真正完成。这种思想在自动化测试里叫断言在网络运维里同样适用。你可以用Python的difflib库做文本差异比对或者直接把两个配置文件丢给diff命令处理。6. 我踩过的坑与并发改造方向6.1 分页符问题备份看起来成功配置其实是残缺的这是所有SSH自动化脚本最经典的一个坑。很多设备默认开启分页输出执行长命令时屏幕输出会停在某个百分比处等待用户按空格继续。Netmiko的send_command在多数情况下会自动处理分页但前提是它认识这台设备的device_type。如果你填错了设备类型或者设备换了一个Netmiko不认识的版本分页符就会原样出现在回显里导致备份不完整。我的解决习惯是在每次连接后、发送采集命令前先执行关闭分页的命令。华为是screen-length 0 temporary思科是terminal length 0H3C是screen-length disable。Netmiko内部其实也会自动做这件事但手动执行一次心里更踏实尤其在面对老设备时。6.2 设备响应慢回显等待时间怎么调另一个高频坑是Netmiko报Read timeout或者命令回显不完整。这往往是因为设备CPU繁忙或网络链路不稳定命令发出后设备迟迟不响应而Netmiko默认的等待时间不够。之前在一次大批量配置下发中我遇到一台核心交换机在配置时明显卡顿Netmiko直接抛超时异常导致整个脚本中断。解决办法是用send_command的delay_factor参数。这个参数的含义是“以默认等待时间为基准的倍率因子”设为2就是等待时间翻倍。比如output conn.send_command(display current-configuration, delay_factor2)如果某台设备特别慢可以临时提高到3或4。但我建议不要把delay_factor全局调大因为那会让所有设备都变慢尤其备份几百台设备时每台多等几秒钟总量就多出几十分钟。合理的做法是默认用1遇到个别慢设备时单独处理。6.3 命令下发过快导致丢弃SSH交互本质是字符流如果连续下发命令速度过快有些设备尤其是老设备会丢字符或者没有正确处理回车符导致命令粘连或者执行错误。Netmiko的send_config_set内置了命令间的微小间隔但如果你用底层的write_channel直接发送原始数据就要自己控制发送节奏。我在自己封装协议时会用time.sleep做命令间延时但用Netmiko时通常不用操心这个问题。唯一要注意的是command_timeout参数它控制的是单条命令的整体超时时间而不是命令间延时。理解这几个超时参数的区别排查问题时会少走很多弯路。6.4 并发改造从串行到批量效率倍增串行执行最大的问题就是慢。备份100台设备每台耗时5秒就是500秒差不多8分多钟。对于备份这种操作时间还勉强能忍受如果是巡检或者批量查询时间一长配置信息就失去了实时性。这时候就需要并发改造。Python做并发最简单的方式就是用concurrent.futures的ThreadPoolExecutor。Netmiko的SSH连接本身是I/O密集型操作等待网络响应的过程CPU并不忙用多线程能获得接近线性的提速。看这个改造后的批量备份代码片段from concurrent.futures import ThreadPoolExecutor, as_completed def batch_backup_concurrent(devices, max_workers10): results {} with ThreadPoolExecutor(max_workersmax_workers) as executor: future_map {executor.submit(backup_single_device, dev): dev[host] for dev in devices} for future in as_completed(future_map): host future_map[future] try: filename future.result() results[host] (success, filename) except Exception as e: results[host] (failed, str(e)) return results这里有三个经验值得分享第一max_workers不要盲目调大。网络设备的SSH服务能力和设备CPU是有上限的并发太多会导致设备日志刷屏、CPU飙升甚至触发设备自身的防扫描机制从而封禁你的IP。我自己一般控制在10到15个并发既能明显提速又不会给设备造成压力。第二并发环境下要控制日志输出的时序。多线程同时执行时日志打印的顺序是乱的所以输出结果时最好统一把结果汇总到一个字典里最后再按固定顺序打印或保存这样可读性好很多。第三异常的捕获一定要在任务函数内部完成不要让异常渗透到as_completed的循环里否则一个设备异常可能导致整个结果汇总逻辑中断。上面代码中backup_single_device内部的try/except就承担了这个职责。6.5 与Jenkins集成的轻量思路脚本写完之后怎么让它被团队方便地使用最简单的方式是接入Jenkins这类CI/CD平台。我把备份脚本和配置下发脚本封装成命令行入口参数包括设备清单文件、动作backup或change、配置文件路径然后在Jenkins里配置一个自由风格的项目用参数化构建触发。这样一来运维同事不需要懂Python只需要在Jenkins界面里选中“备份全网设备”或“批量下发配置”填上要执行的参数点一下构建按钮就能完成操作。构建历史里的控制台输出就是完整的操作日志天然满足审计需求。Jenkins的定时构建还能帮我们实现“每周自动备份一次全网配置”的需求非常实用。6.6 平台化之前先把单点脚本做扎实很多人一上来就想着搞一个大平台融合配置管理、故障监控、自动巡检于一身。我的建议是如果你不是有充足人力的团队别一上来就搞平台先把手里的几个单点脚本做扎实备份脚本、巡检脚本、变更脚本、回滚脚本。单点脚本稳定跑上几个月积累了足够多的真实设备交互数据和踩坑经验之后再考虑平台化那时候你对设备差异、异常模式、网络拓扑的认知已经足够支撑平台设计。我自己就是从一个个脚本起步的每个脚本解决一个具体问题脚本之间通过共同的设备清单文件和日志规范打通慢慢就拼成了一个轻量的自动化运维体系。这个路线对中小团队来说比直接买平台或自研平台更现实也更容易落地。最后再补一个我最近常用的小技巧所有Netmiko脚本在最后断开连接前我会主动执行一次conn.save_config()如果设备支持确保变更的配置持久化到设备的启动配置中。很多设备在运行配置生效后重启就丢了如果自动化脚本没有帮你做save这一步你在设备上做了半天变更一次断电全部打回原形。自动化的意义不只是快还要做到比手工更可靠这就需要把“手工操作时容易忘记的最后几步”也固化到脚本里。本文还有配套的精品资源点击获取
返回列表