
做了十几年网络运维每天最烦的事就是重复敲命令。远程登录一台交换机敲十几条巡检命令截图退出来换下一台接着敲一个上午就这么没了。后来我开始研究SecureCRT的脚本功能用VBScript把这套动作全部自动化脚本一跑几十台设备的状态自动采集、配置自动比对我只需要坐在旁边等结果。这篇文章就把我积累的SecureCRT自动化脚本开发经验完整整理出来包括环境准备、核心对象模型、批量巡检脚本实战、参数化与定时联动、常见报错排查全是2025年实操验证过的方案新手跟着抄就行老手也能在异常处理上找到可借鉴的思路。1. 为什么说SecureCRT脚本是运维提效的第一站1.1 一次批量上线看清脚本的痛点价值先说个真实场景。上个月公司要完成18台接入交换机的端口VLAN调整每台设备需要登录、进入配置模式、修改三个接口的VLAN划分、检查配置生效、保存配置、退出登录。人工一台一台做少说也要一个半小时而且中间只要有一台状态不对停下来排查时间根本没准头。用SecureCRT脚本跑这批任务脚本把“登录—修改—验证—保存—退出”整条链路串联起来每台设备运行时间压到40秒左右18台设备加上异常等待总共也就15分钟。这个时间差还不是最关键的关键是人的注意力有限连做七八台之后很容易把命令敲串行脚本不会。SecureCRT脚本能力的核心价值就三句话把重复操作固化成逻辑、把人为失误从流程里剔除、把巡检和变更时间压缩一个量级。对于经常跟网络设备、Linux服务器打交道的运维人员这几乎是性价比最高的自动化入门方式不需要额外部署Ansible这类工具链只用现有客户端就能干起来。1.2 脚本语言选型VBScript还是JScriptSecureCRT内置支持两种脚本语言VBScript和JScript。网上不少教程推荐VBScript理由很实在案例多、语法对运维人员更友好写起来像在写伪代码。VBScript的优势在于它对大小写不敏感变量声明灵活尤其适合处理设备的串口回显和文本匹配。JScript本质是微软的JavaScript方言对习惯Java或C系语法的朋友更顺手但SecureCRT相关的文档和代码片段里VBScript占比明显更高有问题也更容易搜到答案。我自己日常写脚本用VBScript但有一点必须说明SecureCRT对两者的底层支持完全一致核心对象模型都一样选哪个纯粹看个人习惯。团队协作的场景建议统一用一种方便互相Review代码。如果你是完全零基础直接学VBScript资料多、坑少、容易上手。2. 脚本开发前的准备工作环境、会话和对象模型2.1 环境准备与会话配置要点脚本开发的第一步是准备好SecureCRT环境。我是基于SecureCRT 9.x版本做的验证早期8.x版本同样兼容只是个别属性名写法有差异遇到报错去查对应版本的帮助文档即可。打开SecureCRT在菜单栏找到“Script”菜单选择“Script Manager”这里可以新建、编辑和运行脚本。推荐把脚本文件统一放在一个目录里比如D:\Scripts\SecureCRT\然后用脚本管理器把这个目录设为默认路径后续调用方便很多。会话配置里有几个直接影响脚本运行的点要提前设好。登录设备时的“用户名提示”和“密码提示”字符串脚本里要用Screen.WaitForString精确匹配所以设备登录提示最好保持标准的Username:、Password:。另外连接的“协议”选项建议固定为SSH2或Telnet尽量不要依赖自动检测否则脚本里等待登录成功的时序判断容易错乱。2.2 认识SecureCRT的脚本对象模型写SecureCRT脚本必须理解它的对象模型。整个模型的核心是crt这个顶级对象所有操作都从它发起。最常用的有三个子对象crt.Screen代表终端屏幕核心方法是Send发送字符串、WaitForString等待特定内容出现、Get读取指定行列的字符。crt.Session代表当前连接会话核心属性是Connected判断是否连接常用方法有Connect、Disconnect。crt.Dialog提供弹窗交互用于输入参数、显示消息。打个比方crt.Screen就像你和设备对话的窗口Send是你说话WaitForString是你竖起耳朵听对方说到哪一句了Get是查看当前屏幕上某个位置的文字。理解这三板斧脚本的大门就打开了一半。写入脚本时每行代码默认只做一件事比如crt.Screen.Send(display current-configuration Chr(13))这行代码的意思是通过Screen对象发送一条命令Chr(13)是回车符相当于你敲了回车键。设备收到命令后会回显脚本再用WaitForString等待回显完成这样才能保证时序不出错。2.3 起手式第一个自动化登录脚本先写一个最简单的自动化登录脚本目标场景是自动连接到一台交换机登录成功后在特权模式下执行display version并截取设备型号信息。 连接已配置好的会话 Sub Main 假设已经在SecureCRT中建立了一个会话名为Core-SW01 crt.Session.Connect(Core-SW01) 等待登录提示出现 crt.Screen.WaitForString(Username:) crt.Screen.Send(admin Chr(13)) crt.Screen.WaitForString(Password:) crt.Screen.Send(secret Chr(13)) 等待进入用户视图提示符以 结尾 crt.Screen.WaitForString() 发送命令 crt.Screen.Send(display version Chr(13)) 等待回显稳定这里等待的是命令本身出现在屏幕上 crt.Screen.WaitForString(display version) 截取当前屏幕内容并保存 Dim strOutput strOutput crt.Screen.Get(1, 1, crt.Screen.Rows, crt.Screen.Columns) 写入文件 Dim fso, f Set fso CreateObject(Scripting.FileSystemObject) Set f fso.CreateTextFile(D:\Scripts\output\version.txt, True) f.Write(strOutput) f.Close End Sub这段代码有几个细节值得注意。crt.Session.Connect(Core-SW01)要求会话必须提前在SecureCRT里配置好脚本里写的是会话名而不是IP地址好处是密码、端口号、协议这些信息只需要维护在会话配置里脚本可以专心处理交互逻辑。WaitForString是脚本的重中之重每一轮发送必须等待一个明确的回显内容作为“信标”绝不能盲目sleep。这里等待的是设备的用户视图提示符不同厂商、不同设备提示符不一样写脚本前先手工登录一次观察清楚到底以什么字符串结尾。3. 核心实战批量巡检脚本完全拆解3.1 需求拆解与流程设计批量巡检是所有自动化脚本里最实用、最不容易出问题的场景。以我目前的环境为例需求是自动登录24台网络设备逐台执行巡检命令采集设备运行状态最终输出一份汇总报表。巡检命令清单通常包含display version查看设备软件版本和运行时长display device查看板卡和电源状态display fan查看风扇状态display temperature查看温度display cpu查看CPU占用率display memory查看内存占用率设计思路是外层循环遍历设备列表内层循环逐条执行命令并把输出保存到以设备名命名的独立文件中最后合并汇总。脚本里设备清单可以硬编码在数组里也可以从外部CSV读取我更推荐外部CSV因为设备增删时不需要改动脚本本体。3.2 核心代码实现循环巡检与结果捕获下面给出一个精简但可直接运行的VBScript版本。这个脚本假设所有设备都使用相同的用户名和密码测试环境这样没问题生产环境建议通过参数动态传入。Sub Main Dim arrDevices Dim strUser, strPass, strCmd Dim i 设备清单设备名,IP地址 arrDevices Array(SW01|192.168.1.101, SW02|192.168.1.102, SW03|192.168.1.103) strUser admin strPass admin123 For i 0 To UBound(arrDevices) Dim strName, strIP strName Split(arrDevices(i), |)(0) strIP Split(arrDevices(i), |)(1) 建立Telnet会话此处使用crt.Session.ConnectEx Dim nHandle nHandle crt.Session.ConnectEx(/TELNET strIP, , True) If nHandle 0 Then 连接失败则记录日志 WriteLog 连接失败: strName Else 连接成功开始登录交互 crt.Screen.WaitForString(Username:) crt.Screen.Send(strUser Chr(13)) crt.Screen.WaitForString(Password:) crt.Screen.Send(strPass Chr(13)) 等待进入用户视图 crt.Screen.WaitForString() 执行巡检命令 Dim arrCmds arrCmds Array(display version, display device, display fan, display temperature, display cpu, display memory) Dim j, strAllOutput strAllOutput strName 巡检结果 vbCrLf For j 0 To UBound(arrCmds) strCmd arrCmds(j) crt.Screen.Send(strCmd Chr(13)) 等待命令回显 crt.Screen.WaitForString(strCmd) 简单等待输出稳定 crt.Screen.WaitForString(---- More ----) If 1 1 Then crt.Screen.Send( ) End If 捕获当前屏幕内容 Dim strScreen strScreen crt.Screen.Get(1, 1, crt.Screen.Rows, crt.Screen.Columns) strAllOutput strAllOutput --- strCmd --- vbCrLf strScreen vbCrLf Next 保存单台设备的巡检结果 SaveOutput strName, strAllOutput 退出登录 crt.Screen.Send(quit Chr(13)) crt.Session.Disconnect End If Next crt.Dialog.MessageBox(批量巡检完成) End Sub这个脚本整体流程是“连接—登录—循环抓结果—断开—进入下一台”。有几个细节我反复调试过直接写在这里供参考。3.3 分页处理被坑最多次的地方真实设备执行display命令基本都会分页显示屏幕底部会出现---- More ----如果不处理后面的输出根本不会刷新。这是脚本新手翻车率最高的坑。我用了最朴素的方式等待---- More ----出现后发送一个空格。空格的作用等同于你手工按一次空格翻页。但这里有一个隐患如果某条命令的输出本来就不长根本不会出现---- More ----那WaitForString会一直等到超时。解决办法是设置等待超时。WaitForString的第二个参数就是超时秒数crt.Screen.WaitForString(---- More ----, 3)如果3秒内没出现分页标记说明输出已经结束脚本继续往下走。实测下来超时设置3秒比较合适既能覆盖正常翻页间隙又不会让异常情况拖太久。另一个容易忽略的点是抓屏范围。crt.Screen.Get(1, 1, crt.Screen.Rows, crt.Screen.Columns)表示从第1行第1列开始一直抓到屏幕最后一行最后一列即全屏内容。如果设备开启了“回滚缓冲区”功能这里抓到的只是当前窗口显示的部分不是全部历史输出。需要拼接完整输出时要循环翻页并把每次Get的结果拼接起来或者直接在命令行里用display cpu这类不启用分页的命令变体部分设备支持管道或参数关闭分页具体行为取决于设备型号和软件版本。我的习惯是保留分页处理逻辑因为它通用性最强不依赖设备特定命令。3.4 结果保存与命名规范脚本末尾的SaveOutput子过程负责把巡检结果写入本地文件。命名规范上我推荐用“设备名日期时间”的组合方便追溯Sub SaveOutput(strName, strContent) Dim strDate, strFile strDate Replace(Date _ Time, :, -) strFile D:\Scripts\output\ strName _ strDate .txt Dim fso, f Set fso CreateObject(Scripting.FileSystemObject) Set f fso.CreateTextFile(strFile, True) f.Write(strContent) f.Close Set f Nothing Set fso Nothing End Sub Sub WriteLog(strMsg) Dim fso, f Set fso CreateObject(Scripting.FileSystemObject) Set f fso.OpenTextFile(D:\Scripts\output\error.log, 8, True) f.WriteLine Now - strMsg f.Close Set f Nothing Set fso Nothing End Sub这里有个Windows文件名细节时间字符串里的:在Windows文件系统里是非法字符必须替换掉。我上面用Replace把它替换成-否则CreateTextFile会直接报错。这个小问题当年还真卡了我十分钟。4. 进阶玩法脚本参数化与日程联动4.1 给脚本加参数一套脚本通吃多种场景写死的脚本只能巡检固定设备稍微变一变使用方式脚本复用性就会大幅提升。SecureCRT支持在运行脚本时传参参数在脚本里通过crt.GetScriptArgs获取。举个例子我想让同一个登录巡检脚本既能巡检交换机又能巡检路由器而且每次巡检时不用改脚本内容只要在运行时告诉脚本“去巡检哪些IP”就可以Sub Main Dim arrArgs, strIPList arrArgs crt.GetScriptArgs If UBound(arrArgs) 0 Then strIPList arrArgs(0) Else strIPList InputBox(请输入要巡检的IP列表逗号分隔) End If Dim arrIPs arrIPs Split(strIPList, ,) Dim i For i 0 To UBound(arrIPs) Dim strIP strIP Trim(arrIPs(i)) Call ProcessDevice(strIP) Next End Sub调用方式是在SecureCRT的脚本管理器里右键选择“Run with Parameters”输入192.168.1.101,192.168.1.102脚本就会把这串参数作为参数列表读取。再看下面这个示例crt.Session.ConnectEx(/TELNET strIP, , True)如果希望用不同用户名、不同密码连接不同设备完全可以把用户名密码也做进参数列表里按固定分隔符解析三段IP、用户名、密码。设备巡检、批量升级、批量配置备份本质都是这套逻辑换个参数集就换了一个场景。从实践角度讲参数化脚本比硬编码脚本的维护成本低很多。硬编码脚本每改一次设备清单都要开编辑器改完还要小心别把标点符号改坏参数化脚本则是部署一次、长期使用。这个区别跑过50台以上设备的巡检就会深有体会。4.2 配合Windows任务计划实现无人值守巡检脚本本身只能在你坐在电脑前的时候运行。真正意义上的无人值守还需要配合Windows任务计划程序。我的做法是写一个批处理文件run_inspection.bat内容非常简单echo off D:\Program Files\VanDyke Software\SecureCRT\SecureCRT.exe /script D:\Scripts\SecureCRT\inspection.vbs /arg 192.168.1.101,192.168.1.102这个批处理执行时会静默启动SecureCRT并加载巡检脚本SecureCRT窗口会显示在桌面上脚本跑完后自动退出。然后我在Windows任务计划程序里创建一个每日任务触发器设为每天早上8点操作指向这个批处理文件运行账户设为有权限启动GUI程序的账户。任务计划配置里有几个注意点。运行任务时账户需要设置“只在用户登录时运行”因为SecureCRT是GUI程序如果选择“不管用户是否登录都要运行”SecureCRT可能会因为没有可用桌面会话而无法启动。另外批处理启动的SecureCRT窗口不要最小化到托盘实测某些环境下最小化会影响Send命令的焦点行为导致命令发不出去。如果你想在日志里看到每台设备的执行时间可以在脚本里加一句crt.Screen.Send(display clock Chr(13)) crt.Screen.WaitForString(clock, 3)这样巡检结果里会带上设备当前时间和本地时间做比对能快速发现设备时钟漂移问题。4.3 异常处理设备无响应和登录失败的重试逻辑真实网络环境不可能一帆风顺写脚本必须处理非预期情况。我遇到过的问题类型差不多就这几类设备不响应登录提示、密码错误导致登录循环、命令执行超时、连接闪断。对应的处理策略我在脚本里加了三个判断层级。第一层连接阶段。ConnectEx的返回值是句柄如果为0说明连接失败直接记录日志并跳过该设备不要死等。这个上面代码里已经体现。第二层登录阶段。每次WaitForString都设置超时时间例如等待Username:用10秒超时如果超时还没等到说明登录可能根本没触发记录失败后执行Disconnect并继续下一个设备If Not crt.Screen.WaitForString(Username:, 10) Then WriteLog strName 登录超时 crt.Session.Disconnect GoTo NextDevice End If第三层功能验证。在每台设备巡检结束后做一个“回执检查”比如发送一条display current-configuration | include hostname然后等待设备名出现在回显里以此判断设备是否仍然正常响应。如果设备已经假死这条命令不会返回脚本凭超时判断状态异常并记录日志。有些设备配置了screen-length 0 temporary支持不分页输出这能减少大量等待时间但不是每台都支持我没有把它写进通用脚本只在专门优化的场景里用。用VBScript实现GoTo标签要在循环外定义标签位置VBScript的GoTo不支持跨过程跳转我一般用Exit For配合布尔变量来实现跳过逻辑代码更整洁。这里限于篇幅不展开全部写法抓重点每一轮与设备的交互都必须设置“超时后怎么办”这是脚本稳定运行的底线。5. 常见问题与排错经验速查5.1 高频报错与解决方案表格下面这张表是我在实际使用中整理的高频问题按出现频率排序现象根本原因解决方法WaitForString一直等到超时等待的字符串与设备回显不完全匹配常见问题是漏了空格或大小写写错手工登录设备复制完整的回显字符串粘进脚本Send命令发出去了但设备没反应发送的字符串结尾没有带回车符Chr(13)每条命令末尾必须拼接Chr(13)抓屏内容只显示一页没处理分页符屏幕内容停留在第一页等待---- More ----后发送空格循环翻页文件保存报路径错误Windows不允许文件名包含冒号等字符把日期时间里的冒号替换为-或_脚本运行切不过去窗口SecureCRT窗口没有获得焦点Send被发送到了其他窗口确保SecureCRT窗口在前台任务计划任务不要设置“后台运行”ConnectEx返回0目标不可达或会话配置错误先手工在SecureCRT里连接一次确认网络链路正常命令回显捕获不全Get抓取的是当前屏幕而不是回滚缓冲区多次翻页并拼接每次Get的结果或者关闭分页后再执行命令5.2 抓不到完整回显的排查思路回显抓不完整是我遇到最多的问题表现很有迷惑性脚本运行看着一切正常Saved输出文件里最后一条命令的结果只有半截。排查思路分三步。第一步确认是否翻页中断。如果输出长度远大于一屏必须先检查---- More ----的逻辑有没有真正执行到。最简单的验证是在脚本里加一句临时日志记录每次WaitForString的结果。第二步确认抓屏时机。命令发出后立刻Get抓取设备还没输出完抓到的自然是不完整的内容。必须在发送命令后等待一个命令回显的“尾部标记”比如再等一次提示符。不同设备的提示符不同有的以结束有的以]结束有的包含设备名。写脚本前手工登录一次观察提示符的具体格式是最笨也最可靠的方法。第三步确认屏幕行数设置。SecureCRT默认终端行数是24行列数80到120不等如果Get的参数范围超过了终端实际缓冲多出来的部分就是空白。我在脚本里把Rows和Columns换成实测值Dim nRows, nCols nRows crt.Screen.Rows nCols crt.Screen.Columns这样可以避免硬编码出错。5.3 从单机运行走向批量署理的效率建议脚本跑通单台设备后很多朋友会急着上批量。我的建议是先小批量验证再全量执行先拿两台试点确认输出文件完整无误再扩展到全量。批量执行时设备的顺序也很关键。建议把设备按重要性从低到高排列这样即使脚本有隐藏bug先跑通的是低风险设备不会影响核心业务。我遇到过批量修改VLAN的脚本在测试环境跑得好好的上生产环境第三台设备就因为型号不同导致interface子视图下命令执行报错幸好顺序排的是先测试区设备没伤到核心业务交换机。另外一个容易被忽视的问题是SecureCRT脚本运行时的性能。脚本是用串行方式逐台设备执行的如果设备数量上百总耗时会比较长。我在设备量大的场景会把巡检任务拆成三四个批处理并行跑每个批处理负责一部分设备实测总耗时能缩短到串行的三分之一左右。并行跑增加了日志文件写入的并发处理难度我选择让每个子任务写独立的日志文件不做全局合并汇总时用脚本统一合并各子文件逻辑更清晰。5.4 安全合规边界自动化脚本的几条原则写自动化脚本本质上是在用机器代替人手操作网络设备权限很大责任也很大。这里我必须强调几条原则是我自己踩过坑后用教训换来的。第一条只在获得授权的主机和设备上执行脚本。自动化脚本和手动敲命令完全不同手误还有反悔机会脚本一旦批量下发错误配置影响面是成倍的。所有脚本在写完后先拿一台测试设备验证再走变更审批流程再上生产。第二条高风险操作必须加确认机制。涉及重启设备、清空配置、修改路由这类指令脚本里要加入二次确认逻辑。要么要求输入特定确认词要么在脚本开头弹出Dialog提示框由人工确认总之不允许“一键无脑执行到底”。我自己的做法是给高危命令加一个参数--confirm缺了它脚本直接跳过该步骤。第三条不要用脚本记录明文密码。脚本文件本身是明文存储的如果里面写了登录密码一旦脚本文件泄露等于把所有设备密码拱手送人。正确做法是把密码放在SecureCRT的会话配置里它的密码存储有基本加密能力或者通过环境变量在脚本运行前动态注入脚本内部只引用变量不写具体密码。6. 我的实操心得与后续扩展方向6.1 一套能长期使用的脚本工程目录结构脚本写过几轮之后我发现最大的敌人是脚本文件越来越多、越来越乱。现在我的习惯是固定一套目录结构D:\Scripts\SecureCRT\ ├─ bin\ 存放脚本主体 ├─ conf\ 存放设备清单、参数配置 ├─ output\ 输出结果 ├─ log\ 运行日志 └─ backup\ 脚本历史版本设备清单单独放在conf目录下的CSV文件里脚本通过读取CSV获取设备列表而不是改脚本本体。这样即使设备数量增加几百台脚本主体一行都不用动。写日志这件事也不能省。我每轮执行都会以日期命名日志文件例如log\2025-03-15_inspection.log。出现问题时翻日志找证据比对着屏幕猜原因效率高太多。6.2 基于脚本能力还能扩展什么脚本的基础能力是“和终端交互”这决定了它能干的事远不止巡检。我目前已经在用的扩展方向有三个。第一个是配置备份。每周自动登录所有网络设备执行display current-configuration把输出保存成带日期的配置文件存档。这个脚本跑了一年多支撑了好几次设备故障后的快速回滚。第二个是配置合规检查。脚本从设备拉取当前配置后再用简单的文本匹配逻辑搜索关键项比如登录超时时间、SNMP团体名、日志服务器地址等。跑完之后自动生成一份合规检查报告列出不合规的设备和配置片段。第三个是版本升级辅助。设备升级时脚本自动完成登录、上传版本文件、指定下次启动版本、重启、等待设备重新上线并验证版本号这一整套操作。这个场景对交互时序要求更高但一旦跑通省下的人力是最直观的。如果你平时的工作也离不开跟各种网络设备、服务器终端打交道我建议花一个周末把第一个脚本跑起来从最简单的一台设备登录开始慢慢加循环、加参数、加异常处理。SecureCRT脚本的能力上限比大多数人想象的高得多而入门路径就藏在本文这些基础示例里。脚本开发没有捷径多跑几次、多踩几个坑慢慢就有手感了。