ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

网络设备开局配置生成器:模板化批量生成与验证实战

网络设备开局配置生成器:模板化批量生成与验证实战

简介:网络设备开局配置生成器1.1.6.2正式版是一款面向网络工程师的开局自动化工具,主要解决批量交换机配置耗时、易错的问题,支持华为、华三、锐捷等主流设备的开局脚本快速生成。该工具可在1分钟内生成单台或多达100台的差异化配置脚本,基于SecureCRT的VBS脚本实现自动下发,用户无需掌握脚本语法即可定制并执行,也支持直接复制配置命令手工粘贴。压缩包共8个文件,以6个htm格式的配置说明文档为主,覆盖华为ACL配置示例、华三V7 OSPF多域配置、H3C基础配置及锐捷常用命令速查等典型场景,另有1个Excel批量生成模板和1个主程序exe,整体大小15.15MB。目前已有586人学习/下载。使用这一资源包,读者可获得完整的主程序、可参考的配置文档和批量模板,既能快速生成开局脚本,也能对照示例理解各类协议配置要点,显著提升网络设备开局与维护效率。

1. 网络设备开局配置生成器:批量开局前先过一遍生成器流程

新到一批接入设备,五六个机柜的交换机、防火墙,开局那天如果你还在手敲命令或者从旧文档里复制粘贴,大概率会漏配接口、错配ACL。网络设备开局配置生成器1.1.6.2正式版就是干这个的:你把设备型号、接口规划、VLAN划分、互联地址这些参数填进一张清单,它按照内置模板自动生成每台设备的完整开局配置,批量导出后直接灌进设备。适合做集成项目、日常割接、远程开局的朋友。我拆了这个版本之后,把常用的模板和踩过的坑都整理在下面。整份资源是RAR打包,解压就能用,后面按开箱到排查的顺序讲。

2. 模板引擎的工作方式:为什么开局配置生成器能省下大半配置时间

2.1 配置模板的三层结构:变量、默认值、版本差异

很多第一次用这类生成器的人,以为它就是把Excel表里的IP替换到txt模板里。实际拆开看,1.1.6.2这个版本的模板系统按三层结构组织。第一层是基础配置块,包含设备名、管理口、时区、日志服务器这类全局项,所有设备基本一样,只是个别值不同。第二层是变量占位符,对应每台设备不同的接口名、VLAN、互联地址和描述。第三层是条件块,根据设备型号或角色决定是否输出路由协议、ACL条目、链路聚合这类差异较大的配置段。

三个层次在同一个模板文件里用不同语法标记区分。模板文件用的是类似Jinja2的语法,变量用双花括号包起来,条件块用百分比标记上下包裹。我截取一个接口配置片段,这是开局配置里最常出问题的部分:

{# 接口配置模板片段 #} interface {{ if_name }} description {{ if_desc | default('to-access') }} {% if if_mode == 'trunk' %} switchport mode trunk switchport trunk allowed vlan {{ vlan_list }} {% else %} switchport mode access switchport access vlan {{ access_vlan }} {% endif %} no shutdown

这段模板的逻辑是:先输出接口名,再输出描述。描述字段带了一个default过滤器,清单里没填if_desc时也不会留下空行,而是落到to-access这个默认值。接下来按if_mode的值分两条路走,trunk口输出trunk模式和放行VLAN列表,access口输出access模式和PVID,最后统一加一条no shutdown,避免设备断电重启后接口处于管理性关闭状态。

参数说明:

  • if_name:接口名,建议写全称,比如GigabitEthernet0/0/1,不能简写成gi0/1;
  • if_desc:端口描述,一般写对端设备名和接口,方便后面排障;
  • if_mode:trunk或access,决定走哪一段条件块;
  • vlan_list:trunk允许列表,用逗号分隔,模板会原样输出;
  • access_vlan:access口的VLAN号,只在非trunk场景下引用。

我在模板文件顶部还会放一个版本注释。这个习惯是从一次被模板改崩的经历里学来的。那一次同事改了一个全局参数,所有设备的开局配置都变了,但没人记得是什么时候改的,也没有对照记录。

{# 模板版本:switch/j2/1.1.6.2 #} hostname {{ hostname }} ! no ip domain-lookup ! clock timezone CST +8:00 !

这段比上一段简单,但它的作用是把模板版本写进生成结果。后面不管是查问题还是追溯变更,都能知道这份配置是用哪一版模板生成的。除了变量和条件块,部分模板还支持include引入公共片段。公共片段通常放SNMP、NTP、日志服务器这类所有设备都有的配置。include的好处是改一处就能同步到所有型号模板里,坏处是模板依赖关系变复杂,检查时要额外留意include的文件是否存在。

这套模板机制里还有一个容易被忽略的点:变量作用域。设备清单里每台设备是一个独立作用域,模板里引用的变量都从当前设备条目里查找,不会跨设备混合。这带来一个约定:所有设备条目的字段名必须一致,有的设备写了mgmt_ip,有的写了ip,check阶段就会报未定义变量。所以我在项目里都会在bindings目录放一份devices.yaml.example,当作字段字典用,新设备照抄。

2.2 部署步骤:解压、修改配置文件、首次运行校验

这个版本打包成RAR,我一般先在服务器上建一个独立目录,再解压。Linux下常见做法是:

mkdir -p /opt/netgen rar x network-device-init-gen-1.1.6.2.rar /opt/netgen/ cd /opt/netgen find . -maxdepth 2 -type f | sort

rar命令需要系统装了rar或unrar工具,没装的话先处理依赖;Windows下直接右键解压也行,但后面批量生成、脚本比对都在Linux上更方便,所以我建议直接在Linux环境里跑。find命令的输出会显示config.ini、templates目录、bindings目录和netgen.py主脚本。

解压后第一步不是运行,而是打开config.ini确认输出行为:

vim config.ini

config.ini里需要确认三组键值。我把常见的设置列成一张表:

设置项示例值说明
output_dir./out生成文件输出目录
encodingutf-8输出文件编码,建议全程保持一致
line_endinglf换行符,统一用lf
date_fmt%Y%m%d%H%M归档时用的时间戳格式

encoding和line_ending如果没设对,生成出来的配置会在设备CLI上出问题,后面避坑章会展开说。date_fmt是给输出目录做时间戳用的,配合归档脚本可以避免覆盖旧文件。

改完配置后,先跑一次校验模式,别急着生成:

python3 netgen.py --check --template templates/switch.j2 --bindings bindings/devices.yaml

--check的意思是只加载模板和设备清单,做一遍变量解析,并不真正写入配置文件。它很快,适合反复修改模板时用来验证语法和变量引用。--template指定模板路径,--bindings指定设备参数清单路径。如果模板里有未定义的变量或者清单文件解析失败,程序会在终端报出具体位置和行号,正常情况下退出码是0。

我一般会把校验命令固定写进一条Makefile或者shell函数里,因为开局前连续改清单的情况很多,每改一次就跑一遍check,能省掉后面排查半成品配置的时间。确认校验通过后,才进入正式生成环节。

有人会问,既然只是替换变量,为什么不直接用sed全局替换?关键在于条件块和include。sed处理不了if/else逻辑,也管理不了模板文件之间的依赖,改动一次就要维护一堆sed命令,配置生成器把这些集中到模板引擎里,可维护性高很多。模板本身就是文档,清单字段名一看就知道要填什么,这套机制比复制粘贴强在两点:一是变量解析顺序固定,先读模板再读清单,字段名对不上就报错,不会默默生成错误配置;二是条件块的引入让同一份模板能适配不同型号设备,而不是每个设备单独维护一份全量文档。代价是模板本身的语法需要学习,不过1.1.6.2这种版本内置的语法很少,基本上会if/else就能上手。

3. 生成器实操:从设备清单到批量导出配置的执行流程

3.1 设备清单的格式与字段约束

整个流程的输入是bindings目录下的设备参数清单。我建议用YAML而不是CSV,因为YAML支持嵌套结构,也可以在字段旁边写注释。下面是我常用的一个例子:

# 设备清单 devices.yaml devices: - hostname: CORE-SW-01 model: model-b mgmt_ip: 192.0.2.10 mgmt_mask: 255.255.255.0 vlan_list: "10,20,30,99" uplink: GigabitEthernet0/0/1 loopback: 10.255.255.1 - hostname: ACCESS-SW-12 model: model-c mgmt_ip: 192.0.2.12 mgmt_mask: 255.255.255.0 vlan_list: "10,20" access_vlan: 10

两个设备条目都放在devices这个列表下,每个条目是一台设备。字段命名要和模板里引用的变量一致,否则模板取不到值,在check阶段就会报错。这里有个容易忽略的点:model字段的取值要和模板里的条件分支约定一致。我这里的model-b代表三层汇聚交换机,模板里走trunk上联、下发VLAN的分支;model-c代表二层接入交换机,走access口和默认VLAN的分支。如果清单里出现模板没有约定的model值,条件块会落到else分支,生成结果可能不完整。

字段说明表:

字段是否必填示例说明
hostname必填CORE-SW-01配置里的设备名,不能有空格
model必填model-b决定模板里的条件分支
mgmt_ip必填192.0.2.10管理接口地址
mgmt_mask必填255.255.255.0管理地址掩码
vlan_list可选"10,20,30,99"trunk口放行VLAN
uplink可选GigabitEthernet0/0/1上联接口名
access_vlan可选10access口PVID
loopback可选10.255.255.1环回地址

这里有两个坑。第一,vlan_list字段建议写成带引号的字符串,不要写成YAML数组。因为模板里直接展开成逗号分隔文本,写成数组还得在模板里额外做join处理,容易引入不一致。第二,之前我用CSV版本的工具时,最头疼的是描述字段里一旦出现逗号,整列就被拆开了,设备清单要反复修。换YAML之后没再出过这个问题。

3.2 命令行运行参数与批量导出

单台设备生成时,指定设备名:

python3 netgen.py --template templates/switch.j2 \ --bindings bindings/devices.yaml \ --hostname CORE-SW-01 \ --output out/CORE-SW-01.cfg

--hostname必须和清单里的hostname字段完全一致,大小写也要一致;--output可以直接指定目标文件路径。如果不传--hostname,程序默认把bindings里所有设备各生成一份。

批量生成时我会用一个for循环:

for device in $(yq -r '.devices[].hostname' bindings/devices.yaml); do python3 netgen.py --template templates/switch.j2 \ --bindings bindings/devices.yaml \ --hostname "$device" \ --output "out/${device}.cfg" done

yq是YAML解析命令行工具,如果环境里没装,也可以直接用python读hostname列表跑同样的循环。循环的意义是保证每台设备单独落一个文件,同时文件名和设备名严格对应,后面归档和比对都方便。如果现场同时有交换机、路由器、防火墙,模板就不能共用同一个switch.j2了。我一般会按角色分别建router.j2、firewall.j2,批量脚本里再根据设备型号选择模板路径,避免把二层交换机的VLAN配置套到防火墙上。命令行参数里还有个--format,默认是cfg,表示纯文本配置,如果只要JSON格式的配置树,可以传--format json,导出的结果适合给自动化平台做进一步处理,但常规开局用cfg就够。

3.3 输出目录结构与人工复核点

生成结束后,看输出目录:

tree out/ log/

输出内容大致是这样:

文件路径说明
out/CORE-SW-01.cfg汇聚交换机最终配置
out/ACCESS-SW-12.cfg接入交换机最终配置
out/manifest.json本次生成记录
log/generate.log运行日志

manifest.json值得单独强调,它记录了每个输出文件对应的模板路径、清单路径、生成时间。出现配置问题的时候,先看manifest确认用的是哪个模板版本,再决定要不要回溯模板改动,没有这个文件时,出了问题只能靠猜。

即使check通过、生成成功,我仍然会做一轮人工复核。重点看四个位置:一是接口名是不是全称,模板默认写了GigabitEthernet0/0/1,现场如果实际叫Ten-GigabitEthernet0/0/1,就要改模板而不是改清单;二是VLAN列表有没有漏掉管理VLAN,漏了管理VLAN会导致开局后设备失联;三是管理IP掩码和网关是否匹配,掩码错误在模拟环境里往往暴露不出来;四是ACL编号是否符合现场约定,编号错了轻则策略不生效,重则把管理面挡住。人工复核不用花很多时间,但它的价值在于拦截那些模板变量解析检查覆盖不到的语义错误,脚本只能保证语法正确,不能保证配置符合网络规划。

4. 生成配置的验证闭环:在模拟环境里过一遍再上真机

4.1 配置回读的检查项

配置文件直接灌进生产设备之前,我建议至少先过一遍模拟环境。常见做法是拿厂商提供的模拟软件或开源模拟环境,开一台同型号设备,把新生成的cfg内容粘贴进去,再看设备端报不报错。模拟环境里没有生产流量,错误随便翻车,代价比在真机上低得多。我一般按下面的顺序检查:

  • 接口状态:配置里的接口名能否被设备识别,接口是否都包含no shutdown;
  • VLAN数据库:设备上是否出现清单里定义的所有VLAN,trunk口放行列表是否完整;
  • 路由表:三层设备上能否看到直连路由,OSPF或BGP邻居是否建立;
  • 管理面:从模拟环境里的管理主机能否ping通管理地址,入方向ACL有没有把管理网段挡掉;
  • 链路聚合:如果有port-channel,成员口和聚合口是否都配置正确;
  • 设备名和域名:hostname和domain-name是否按规划输出,有没有被粘贴时的手误改掉。

这六项里最容易翻车的是接口名。不同厂商的接口命名规则不一样,模板里写成GigabitEthernet0/0/1,设备实际叫GigabitEthernet1/0/1,配置粘贴时设备会当场报错,后面所有命令中断。模拟环境的价值就是把这类低级错误拦在真机之前。另一个容易被忽略的是VLAN数据库,设备默认只有VLAN 1,如果清单里的VLAN列表没生效,生成配置里即使有trunk放行语句,实际也没有对应VLAN存在,开局后业务就断了。模拟环境里可以用show vlan快速确认,不用等真机接上线才发现。

4.2 用脚本比对两张配置的差异

如果是割接或者批量替换设备,手里往往有一份旧参考配置。生成器产出的新配置要和旧配置做差异比对。我习惯用Python脚本,比肉眼diff靠谱:

#!/usr/bin/env python3 import difflib import sys def read_config(path): with open(path, 'r', encoding='utf-8') as f: return f.read().splitlines() if __name__ == '__main__': original = read_config(sys.argv[1]) generated = read_config(sys.argv[2]) diff = list(difflib.unified_diff(original, generated, lineterm='', fromfile='original', tofile='generated')) if not diff: print("配置一致,无差异") else: print("配置存在差异,前面40行如下:") print('\n'.join(diff[:40]))

脚本逻辑很简单:read_config把配置文件按行读成列表,difflib.unified_diff生成统一格式的差异,空了就输出一致,否则输出前40行。第一个参数传旧配置,第二个参数传新配置。我一般把它当回归工具用:模板改动之后,重新生成一遍配置,和上次生成的结果做diff,看是否只有预期变化。如果出现计划外差异,说明模板里某段条件块被误改了,这时再去看模板变更记录,定位成本很低。

真机上线后,还要把设备实际配置导出来,和生成器的输出再比一次。这一步容易被跳过,但它的意义很大:设备默认配置里经常带一些隐藏参数,比如默认路由、默认放行规则,生成器模板写的是纯净配置,回读结果和它往往对不上。差异项需要工程师逐个确认,不能让脚本直接判定对错。如果时间紧张,至少把接口、VLAN、路由三段的差异看一遍。配置比对脚本不用写得复杂,重点是养成每次开局后都留一份diff记录,有了记录,下次类似项目开局时可以直接参考,不用重新猜设备被改过什么。

5. 开局配置生成器避坑:六个真实踩坑记录

5.1 漏填变量,生成的配置出现空行

现象:生成出的cfg文件里,description那一段是空的,switchport trunk allowed vlan后面也没有任何内容,设备上VLAN放行直接失效。

原因:清单里漏填了vlan_list字段,模板里又直接引用这个变量,没有给默认值。Jinja2风格的模板解析空值时会输出空字符串,不会主动报错,于是配置文件里就出现了残缺行。

解决:给模板变量加上default过滤器,并生成前强制跑一次--check。我在实际工作中会额外写个必填字段校验,把hostname、model、mgmt_ip这些核心字段在跑生成器之前先检查一遍,漏了就直接退出。

5.2 换行符混用导致设备CLI解析异常

现象:把配置文件内容粘贴到设备命令行后,前十几行好像被吞掉了,有的行报unknown command,设备进入一种错乱状态。

原因:生成器在Windows上运行时按CRLF换行输出,Linux上生成的是LF,两种文件混用后,设备CLI把回车符当成了命令的一部分,粘贴几百行后粘贴内容就错位了。

解决:统一用LF。生成前在config.ini里设line_ending=lf;已经生成的文件用dos2unix转一遍再粘贴。

dos2unix out/*.cfg

这条命令处理所有cfg文件,把CRLF批量转成LF。我在所有Linux服务器上都会装dos2unix,因为它不只用来处理生成器的输出,手工从Windows拷过来的旧配置也经常需要转。

5.3 批量生成的密码不一致

现象:同一批设备生成的配置里,有的enable密码是明文,有的是加密串,现场按规划密码登录时发现部分设备密码对不上。

原因:模板里部分地方用了生成器内置的密码哈希函数,部分地方直接引用清单里的明文密码字段。两台设备清单格式不一致,导致生成结果不统一。

解决:密码统一交给生成器的密码模块处理,清单里不写明文,模板里也不直接引用明文密码字段。如果这个版本不具备密码加密能力,至少要在模板层面对所有密码字段做一致的标记,并在生成后抽检两个文件比对,别只抽查一台。

5.4 模板命令超出设备版本的兼容范围

现象:配置灌进设备后,终端报% Invalid input detected,后面的命令全部中断,设备配置到一半就停了。

原因:模板里用了新版本固件才支持的命令,老版本识别不了。常见误用是把一份新设备的配置直接套到老设备上,命令格式不兼容。

解决:在模板里加固件版本条件块,按firmware字段区分输出内容。

{% if firmware == 'old' %} no ip http server {% else %} no ip http server secure-server {% endif %}

同时,在设备清单里增加firmware字段,和model字段一起作为条件判断的依据。这样同一个模板能同时覆盖新旧设备,不用在开局现场临时改配置。

5.5 中文注释乱码

现象:配置文件里所有中文注释都变成乱码,粘贴进设备后显示为一串问号。

原因:模板文件保存成了UTF-8带BOM格式,生成器输出时没有统一编码,设备CLI只认无BOM的UTF-8,于是中文注释全部错位。这个现象在纯英文配置里根本发现不了,一旦有中文就立刻暴露。

解决:在config.ini里把encoding设为utf-8,同时检查模板文件的保存方式,不要带BOM。如果编辑器默认保存带BOM,需要另存为UTF-8无BOM。

5.6 重复执行覆盖了已归档配置

现象:重新跑批量生成后,out目录下同名cfg文件被覆盖,旧配置找不回来了。

原因:输出文件名直接用设备名,没有带时间戳,生成器也没有自动备份机制,重新执行时直接覆盖。

解决:让输出目录带时间戳,或者用一个简单的后处理脚本备份:

backup_dir="backup/$(date +%Y%m%d%H%M)" mkdir -p "$backup_dir" cp -r out/*.cfg "$backup_dir/"

这行脚本把每次生成的结果按分钟级时间戳归档到backup目录,即使后面发现模板改错了,也能随时回退到上一次生成结果。

6. 把生成器纳入工具链:用校验脚本卡住最后一道关口

6.1 配置健康检查的十个检测点

生成完之后,除了diff,我还会跑一组关键词检查,相当于给配置做体检。十项如下:hostname是否等于清单里的设备名;管理接口是否含no shutdown;VLAN id是否完整;ACL里是否放行了管理网段入站;时钟和时区是否设置;SNMP配置是否出现在模板化位置;远程管理端口是否开启;默认路由是否指向正确网关;密码字段是否出现明文;文件名与设备名是否一致。不是所有网络都适用这十项,但开局场景八九不离十。

检查可以用grep片段逐个做,例如:

for cfg in out/*.cfg; do grep -q "no shutdown" "$cfg" || echo "$cfg: 缺少no shutdown" done

这段循环对out目录下每个文件检查no shutdown,缺失就打印文件名和提示。把十项检查都改成类似的一句判断,跑完再进模拟器,比直接灌设备稳得多。

6.2 从生成器到设备的一条龙习惯

我最后一次因为配置漏项导致割接失败,就是省掉了模拟器回读那一步。从那以后,我每次开局之前,不管多着急,都强制走一遍生成→check→模拟器验证→diff→归档的流程。生成器只负责把模板和清单变成配置,效率高,但它不会替你做网络规划,也不会发现模板语义错误,质量还是得靠流程兜底。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进