简介:面向网络运维人员与Python初学者的轻量自动化工具包,聚焦如何通过SSH协议批量连接交换机并下发命令,解决多设备重复配置效率低下的问题。脚本基于paramiko实现,并读取hosts.txt与commands.txt,分别存放交换机IP列表和待执行命令清单,方便使用者按需维护,无需改动代码即可扩展设备规模。资源共3个文件,包含1个Python脚本和2个文本模板,压缩包仅2KB,结构精简,适合快速上手。已有169人学习下载。除可直接运行的SSH连接与命令执行脚本外,还体现了异常处理、结果输出等基础思路;读者可据此改造为带日志记录或并发执行的运维工具,也可结合netmiko等库进一步实现配置备份、批量巡检等场景。
1. 网络运维里最耗时间的动作:手动登录交换机敲命令
如果你管过几台、几十台交换机,大概率经历过这样的场景:接到一个需求,要把全网接入层设备的某个 VLAN 接口配置统一改掉,或者收集所有设备上某个接口的流量统计。于是你打开终端工具,一台一台登录,输入用户名密码,敲命令,截图或者复制粘贴,退出,再登录下一台。十台以内还能接受,几十台下来,半天就没了,中间还容易漏记某台设备的回显。Python 连接交换机自动执行命令,就是把这套重复劳动交给脚本去做的方案:用 SSH 协议连上设备,自动完成登录、进入特权模式、逐条下发命令、抓取回显并保存。这套东西适合正在做网络运维但没写过自动化脚本的人,也适合已经用着工具但想摆脱手工批量操作的从业者,它解决的核心问题是:把「登录—敲命令—存结果」这一连串动作变成一条可重复执行的脚本命令。
2. 从 SSH 到脚本化:连接交换机前的选型与协议基础
2.1 SSH 协议与设备侧配置:为什么脚本能接管命令行
交换机的命令行管理方式主要有 Telnet 和 SSH 两种。Telnet 是明文传输,用户名密码和命令内容在网络里裸奔,生产环境基本不推荐;SSH 是加密通道,脚本连接交换机时默认走的就是 SSH 协议。你手动用终端工具登录,本质上也是建立一个 SSH 会话,然后在这个会话里发送命令、读取回显。脚本做的事情和人一样,只是把「交互式敲键盘」变成了「程序化发送字符串」。
需要确认的是设备侧的 SSH 服务开启状态。不同厂商的交换机开启方式略有差异,但逻辑一致:生成加密密钥、启用 SSH 服务、配置认证方式。以常见的企业级交换机为例,设备上需要确保有 host key,并且 vty 线路下配置了 transport input ssh 或 transport input all。如果设备还是老旧的、只开了 Telnet,脚本就得改用 telnetlib 或模拟终端方式,但那属于兼容方案,遇到这种情况我会优先建议先把设备侧 SSH 打开,别让安全问题留在那里。
另外一个关键点是设备的分页输出。手动操作时,输出一屏会停下来等你按空格,这叫分页。脚本执行时如果碰到分页,命令发出去了,但结果只回了一屏就不动了,脚本会一直卡在读回显的地方。处理方式一般是登录后先发一条关闭分页的命令,比如 screen-length 0 temporary 或 terminal length 0,具体命令看厂商。这一步非常重要,我在后面避坑章节里会专门展开。
2.2 选型对比:paramiko 与 netmiko 的边界
Python 生态里连接交换机最常用的两个库是 paramiko 和 netmiko。paramiko 是底层 SSH 实现,它只负责「建立 SSH 连接、收发数据」,不管设备是什么品牌,也不帮你处理命令回显的边界。netmiko 是在 paramiko 之上封装的网络设备专用库,它对不同厂商的设备做了适配,屏蔽了登录提示符、分页关闭、特权模式切换等差异。
我的建议是:如果只是临时连几台设备,用 paramiko 完全够用,还能让你看清 SSH 连接的本质;但如果你要写一个要长期维护、要覆盖多种品牌设备的脚本,直接用 netmiko,省下的事情远比引入一个依赖多。netmiko 内部处理了很多坑,比如设备回显里的 prompt 匹配、enable 模式的切换、分页关闭命令自动下发,这些如果用 paramiko 裸写,全部要自己处理。
从依赖面看,netmiko 会把你带进 paramiko 生态,所以没有「用了 netmiko 就不用 paramiko」的说法,而是在 paramiko 之上多了一层设备适配。选型时还要考虑执行环境有没有网段限制,如果脚本所在机器到交换机管理网段不通,换什么库都没用。
2.3 环境准备与连接参数:一个能跑起来的最小骨架
先准备 Python 环境,建议 3.8 以上版本。虚拟环境里安装依赖,没有特殊网络环境的情况下一条命令就能完成:
python -m venv netops_env source netops_env/bin/activate pip install netmiko paramiko创建虚拟环境是为了隔离依赖。netmiko 会依赖 paramiko,所以装 netmiko 时 paramiko 会被一起装进来,但单独写一两行字把它点出来,是方便你在排查问题时意识到底层是 paramiko 在管连接。接着准备设备连接参数,netmiko 的核心参数是 device_type、host、username、password,其中最需要注意的是 device_type,它决定了 netmiko 用哪一套交互逻辑去适配设备。
from netmiko import ConnectHandler device = { "device_type": "huawei", "host": "192.0.2.10", "username": "netadmin", "password": "your_password", "port": 22, "timeout": 30, "conn_timeout": 15, } with ConnectHandler(**device) as conn: output = conn.send_command("display version") print(output)这段代码是连接交换机的最简骨架。device_type 填的是厂商和系统类型,netmiko 支持的取值包括 cisco_ios、huawei、hp_comware、arista_eos 等;timeout 是单条命令的执行超时,conn_timeout 是建立 TCP 连接的超时。password 这块我先用占位符,生产环境不建议明文写在脚本里,后面会有专门章节讲怎么处理。
运行脚本后如果打印出了设备版本信息,说明连接链路、认证、命令发送、回显读取这一整条链路都已经通了。接下来的章节把这套骨架展开,逐步加上健壮性处理。
3. 核心脚本:连接交换机并自动执行命令的完整流程
3.1 连接建立与身份认证:先解决"连得上"的问题
连接建立这一步,netmiko 的 ConnectHandler 会把 TCP 连接、SSH 握手、用户名密码认证、登录后进入用户视图这几个步骤全部封装掉。真正要关注的是认证失败和连接超时两个分支。认证失败时设备返回的提示是 Authentication failed,这时候脚本要做的不是继续执行,而是记录下来并跳到下一台设备。
from netmiko import ConnectHandler from netmiko.ssh_exception import NetmikoAuthenticationException, NetmikoTimeoutException device = { "device_type": "huawei", "host": "192.0.2.11", "username": "netadmin", "password": "wrong_password", "timeout": 20, } try: conn = ConnectHandler(**device) output = conn.send_command("display clock") print(output) conn.disconnect() except NetmikoAuthenticationException: print(f"{device['host']} 认证失败,请检查用户名或密码") except NetmikoTimeoutException: print(f"{device['host']} 连接超时,请检查管理地址是否可达、SSH服务是否开启")逻辑说明:try 块里做连接和命令执行,两个 except 分别捕获认证失败和超时。认证失败时不需要重试,直接标记设备并跳过,因为重试只会加重设备侧的登录失败锁定风险;连接超时则需要区分原因,可能是网络不通,也可能是设备 SSH 服务没起。捕获异常后打印的提示信息里带上了主机地址,方便事后定位是哪台设备出了问题。
参数说明:timeout 是命令执行等待时间,conn_timeout 建议单独设置。某些设备在 SSH 握手阶段处理很慢,如果 conn_timeout 设太短,可能出现「设备其实活着但脚本报超时」的误判。我一般把 conn_timeout 设成 15 秒,timeout 设成 30 秒,如果设备特别慢再往大调。
3.2 命令发送与回显捕获:从 send_command 到异常处理
连接建立后,最常用的方法是 send_command。它会向设备发送一条命令,然后把回显全部读出来。这里有一个隐藏逻辑:netmiko 发送命令后,会一直读取输出,直到再次匹配到设备的提示符,才算这条命令执行完成。所以 send_command 返回的字符串是完整回显,不是半截。
实际使用中,命令回显的数据量差异很大。查询接口状态可能只有几行,查询完整配置可能几百上千行。netmiko 内部根据设备型号自动处理了分页问题,但如果是用 paramiko 裸连,就得自己想办法。下面这段代码展示用 netmiko 执行多条命令并分别保存回显:
from netmiko import ConnectHandler import datetime device = { "device_type": "huawei", "host": "192.0.2.12", "username": "netadmin", "password": "your_password", } commands = ["display version", "display interface brief", "display vlan"] conn = ConnectHandler(**device) timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") for cmd in commands: output = conn.send_command(cmd) filename = f"{device['host']}_{cmd.replace(' ', '_')}_{timestamp}.txt" with open(filename, "w", encoding="utf-8") as f: f.write(output) print(f"命令 [{cmd}] 的回显已保存到 {filename}") conn.disconnect()逻辑说明:commands 列表里放的是要在设备上执行的命令,循环里逐条执行并写入独立文件。文件名里带上了设备 IP、命令关键字和时间戳,这样事后找某台设备某条命令的结果时非常直接。执行完所有命令后再统一 disconnect,避免频繁建立连接。
参数说明:如果某条命令执行时间特别长,可以给 send_command 加 read_timeout 参数,例如 conn.send_command("display cpu", read_timeout=60)。不使用这个参数时,netmiko 默认用的是连接时设置的 timeout 值。另有一个场景是命令需要进入交互确认,比如清空某类配置时设备会问确认,这时候 send_command 不够用,要用 send_command_timing,按设备提示逐次发送确认指令。
3.3 执行模式切换与特权命令:enable 与 config 模式的处理
交换机的命令分视图。用户视图下只能做查询,进入系统视图后才能改配置,某些设备还有单独的特权模式,用来执行 save、reboot 这类高危操作。netmiko 用 send_command_timing 或者直接调用 enable() 方法来处理模式切换。
from netmiko import ConnectHandler device = { "device_type": "huawei", "host": "192.0.2.13", "username": "netadmin", "password": "your_password", "secret": "enable_password", } conn = ConnectHandler(**device) conn.enable() output = conn.send_command("display current-configuration") print(output) conn.disconnect()逻辑说明:enable() 方法完成从用户视图到特权模式的切换,设备提示输入 enable 密码时,netmiko 自动用 secret 参数里配置的密码去应答。有的设备开启 local privilege level,enable 密码和登录密码是同一个,这种情况下 secret 可以和 password 填一样。进入特权模式后,可以执行 save、reboot 之类的特权命令,但这类命令有风险,我在后面会建议加确认机制。
参数说明:secret 参数不是必填,但如果设备配置了 enable 密码,不传这个参数,enable() 执行时会因为无法应答密码而失败。某些设备上进入系统视图也用 enable(),某些则必须先 send_command("system-view") 再执行配置命令,最好先在测试环境里确认设备行为再铺开。
如果要在配置模式下批量下发配置,需要逐条发送命令并确认回显。netmiko 的 send_config_set 可以接受一个命令列表并进入配置模式逐条下发,但它依赖设备提示符匹配,遇到不同厂商差异时需要反复验证。我一般把配置下发类操作单独封装一个函数,先做全量测试再上生产。
4. 批量执行与安全加固:让脚本真正落地到生产环境
4.1 批量交换机执行:串行与线程并行的取舍
单台设备的脚本跑通后,自然会想到对一批设备执行同样命令。最简单的方式是循环,一台一台串行处理。
from netmiko import ConnectHandler from netmiko.ssh_exception import NetmikoAuthenticationException, NetmikoTimeoutException devices = [ {"device_type": "huawei", "host": "192.0.2.21", "username": "netadmin", "password": "your_password"}, {"device_type": "huawei", "host": "192.0.2.22", "username": "netadmin", "password": "your_password"}, {"device_type": "huawei", "host": "192.0.2.23", "username": "netadmin", "password": "your_password"}, ] for device in devices: try: conn = ConnectHandler(**device) output = conn.send_command("display cpu") print(f"=== {device['host']} ===") print(output) conn.disconnect() except (NetmikoAuthenticationException, NetmikoTimeoutException) as e: print(f"{device['host']} 执行失败: {str(e)}")逻辑说明:devices 列表里维护一批设备连接参数,for 循环逐台连接、执行、退出。这样写的好处是逻辑清晰,失败时能明确知道是哪台设备出的问题。几十台设备以内,串行执行完全够用,一台设备耗时几秒,二十台也就是一两分钟的事。
当设备数量达到上百台时,串行等待时间会比较明显,这时考虑用线程池并发执行:
from concurrent.futures import ThreadPoolExecutor, as_completed from netmiko import ConnectHandler def run_on_device(device): host = device["host"] try: conn = ConnectHandler(**device) output = conn.send_command("display memory") conn.disconnect() return host, output except Exception as e: return host, f"ERROR: {str(e)}" devices = [...] # 同前 with ThreadPoolExecutor(max_workers=10) as executor: futures = {executor.submit(run_on_device, dev): dev["host"] for dev in devices} for future in as_completed(futures): host, result = future.result() print(f"=== {host} ===") print(result)逻辑说明:ThreadPoolExecutor 创建线程池,把每台设备的连接和执行任务丢进去并行跑。max_workers 是并发数,也就是同时建立多少个 SSH 连接。返回结果用 as_completed 收集,谁先执行完谁先处理,不需要等待所有任务结束。
参数说明:max_workers 的取值要克制。并发数太高,设备侧 SSH 连接数会冲破限制,常见的报错是 "No more connections" 或者连接被重置。我一般根据设备型号把并发压在 5 到 15 之间,老设备并发更小。线程并发的收益在设备数量多时才明显,别一上来就上并发,很多生产事故就是并发过大导致管理网段带宽被顶满。
4.2 密码与密钥管理:不让明文口令留在脚本里
脚本里写死密码是最省事、也最危险的做法。只要脚本文件被传阅、被提交到代码仓库,口令就等于泄露了。常见做法是用环境变量或者本地密钥库来存放口令。环境变量的方式改动最小:
import os from netmiko import ConnectHandler device = { "device_type": "huawei", "host": "192.0.2.31", "username": os.environ.get("NET_DEVICE_USER"), "password": os.environ.get("NET_DEVICE_PASS"), } conn = ConnectHandler(**device) output = conn.send_command("display clock") print(output) conn.disconnect()逻辑说明:运行时从环境变量里读取用户名和密码。脚本本身不包含明文口令,即便文件被拷走,拿不到运行环境里的环境变量就没法连设备。执行前在 shell 里设置环境变量,或者在 CI 平台里配置好对应的 secret 项。
我在生产环境里一般两种方式结合:CRT 工具连接时用 SSH key,但脚本执行的时候仍然用口令,因为很多老设备并不支持密钥认证。这种情况下口令的存放建议用专门的密钥管理工具,避免散落在各台机器上。密码变更后,只需要更新密钥库,脚本本身不用动。
4.3 结果落盘与日志:执行完以后怎么回溯
批量执行完,结果如果只打在屏幕上,事后回溯非常痛苦。我会把每次执行的任务信息、设备 IP、命令、回显全文、执行状态写成一个带时间戳的目录,目录下每台设备一个文件。
import os import json import datetime from netmiko import ConnectHandler devices = [ {"device_type": "huawei", "host": "192.0.2.41", "username": "netadmin", "password": "your_password"}, {"device_type": "huawei", "host": "192.0.2.42", "username": "netadmin", "password": "your_password"}, ] task_time = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") base_dir = f"task_{task_time}" os.makedirs(base_dir, exist_ok=True) summary = [] for device in devices: host = device["host"] result = {"host": host, "status": "OK", "error": None, "output": None} try: conn = ConnectHandler(**device) output = conn.send_command("display version") conn.disconnect() result["output"] = output with open(os.path.join(base_dir, f"{host}.txt"), "w", encoding="utf-8") as f: f.write(output) except Exception as e: result["status"] = "FAILED" result["error"] = str(e) summary.append(result) with open(os.path.join(base_dir, "summary.json"), "w", encoding="utf-8") as f: json.dump(summary, f, ensure_ascii=False, indent=2) for item in summary: print(f"{item['host']} - {item['status']}")逻辑说明:每个任务运行前生成一个 task_ 前缀的时间戳目录,避免多次运行结果互相覆盖。设备回显写入以 IP 命名的文本文件,执行状态、错误信息汇总到 summary.json 里。脚本跑完,扫一眼 summary 就能知道哪些设备成功、哪些失败,不需要逐个打开文件。
参数说明:json.dump 里设置 ensure_ascii=False,是为了让中文错误信息在 JSON 文件里保持可读。indent=2 让文件结构清晰,方便直接用文本编辑器查看。如果后续要做数据统计,也可以把 summary 存成 CSV,用 pandas 或 Excel 打开处理。
5. 避坑:连接交换机时常见的五个翻车现场
5.1 未知主机密钥导致连接中断
现象:脚本第一次连接某台设备时报错,提示 Host key not found 或 Server host key 不匹配,程序直接退出。
原因:SSH 客户端首次连接时会检查设备的主机密钥,不存在或者与 known_hosts 中记录的不一致时,客户端会拒绝继续。netmiko 内部用 paramiko 实现 SSH,默认策略会校验 host key,新设备自然而然触发这个问题。
解决:在设备连接参数里指定 SSH 策略,或者在环境层面统一管理 known_hosts 文件。最常见的做法是允许未知主机密钥加入,但生产环境要注意中间人风险,更稳妥的是先手动连接一次,把设备密钥加入 known_hosts:
from netmiko import ConnectHandler device = { "device_type": "huawei", "host": "192.0.2.51", "username": "netadmin", "password": "your_password", "conn_timeout": 15, } conn = ConnectHandler(**device) output = conn.send_command("display clock") print(output) conn.disconnect()如果仍然报 host key 相关错误,可以改用 paramiko 的 AutoAddPolicy,但这属于「临时绕过」的范畴,长期维护时不建议全局使用。更好的方案是让脚本维护一个独立的 known_hosts 文件,把设备密钥变更纳入变更审批流程,而不是静静地自动接受。
5.2 分页导致输出被截断
现象:发送 show running-config 这类长输出命令,回显只返回了第一屏,后面的内容一直没有输出,脚本长时间不返回或返回残缺内容。
原因:设备默认开启了分页显示,输出满屏后等待用户交互,脚本不发送空格或回车,设备就一直等待下去。
解决:登录后先关闭分页。netmiko 在连接时根据设备类型做了适配,多数主流设备会自动执行关闭分页命令,例如思科设备发 terminal length 0,华为设备发 screen-length 0 temporary。但如果你用 paramiko 裸写,必须在登录后手动发送关闭分页命令,否则输出必断。关闭分页的命令要确认临时生效还是永久生效,还是用临时参数比较保守,避免改了设备配置。
5.3 特权模式切换失败
现象:调用 enable() 后收到错误提示,或者后续命令返回权限不足,某些 display 命令能执行但 save 命令被拒绝。
原因:设备配置了 enable 密码,但脚本的 secret 参数没有设置;或者设备使用本地用户提权,enable 密码和登录密码不同。部分设备还需要再 send_command("enable") 之后额外等待一个交互提示,netmiko 的 enable() 没等到预期提示符就会超时。
解决:确认设备上 enable 密码是否存在、是否与登录密码一致,然后把正确的密码填到 secret 参数里。仍不稳定时,用 send_command_timing 手动完成 enable 过程,先发 enable,读到 Password: 提示后再发密码,这样交互过程完全可控,也方便打日志排查。
5.4 缓冲读取时的空结果
现象:send_command 返回了空字符串,或者只返回命令本身但没有回显内容;偶发情况下同一段代码这次成功、下次却是空的。
原因:设备响应慢,命令发出后回显还没到,netmiko 的读循环就已经超时返回了;或者命令本身无输出但被误判为正常。缓冲区的读取时机和设备的回显速度之间存在竞态。
解决:给 send_command 显式设置 read_timeout,并适当调大。如果命令确实可能有空回显,改用 send_command_timing,并在其后主动读取设备提示符之前的全部数据。另外排查执行环境是否存在代理或跳板机,代理的超时同样会导致回显读取失败。
5.5 并发连接过多导致设备拒绝
现象:批量脚本并发数调到 20、30 后,部分设备报 SSH 连接被拒绝,或者连接建立但认证立刻失败;设备 CPU 在任务执行期间飙高。
原因:多数交换机的 SSH 服务有最大连接数限制,通常个位数到十几个,超过后新连接直接拒绝。线程并发方式下,所有线程几乎同时发起连接,很容易打破这个上限。
解决:把 max_workers 调整到设备能接受的范围之内,比如 5 左右,单台设备执行完再释放连接。确认设备侧 ssh server session 限制配置,必要时调整。并发场景下还容易出现设备侧登录锁定,账号密码错误次数多了设备会把来源 IP 列入黑名单,这种情况连手动登录都会受影响,只能等待锁定超时或手工解锁。
6. 进阶:把脚本固化成定时巡检任务
6.1 生成巡检报告并输出 CSV
单次执行已经能解决很多问题,但如果想让它发挥持续价值,下一步是把脚本变成定时巡检工具。巡检的核心是「按固定周期抓关键指标、对比历史数据、发现异常」。我把设备信息输出整理成 CSV,方便后续用电子表格处理。
import csv from netmiko import ConnectHandler devices = [ {"device_type": "huawei", "host": "192.0.2.61", "username": "netadmin", "password": "your_password"}, {"device_type": "huawei", "host": "192.0.2.62", "username": "netadmin", "password": "your_password"}, ] rows = [] for device in devices: try: conn = ConnectHandler(**device) version = conn.send_command("display version") cpu = conn.send_command("display cpu") mem = conn.send_command("display memory") conn.disconnect() rows.append({ "host": device["host"], "version": version.splitlines()[0] if version else "", "cpu": cpu.splitlines()[1] if len(cpu.splitlines()) > 1 else "", "memory": mem.splitlines()[1] if len(mem.splitlines()) > 1 else "", }) except Exception as e: rows.append({"host": device["host"], "version": f"ERROR: {e}", "cpu": "", "memory": ""}) with open("inspection_report.csv", "w", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=["host", "version", "cpu", "memory"]) writer.writeheader() writer.writerows(rows) print("巡检报告已生成: inspection_report.csv")逻辑说明:每台设备抓取版本、CPU、内存三类信息,经过简单的文本截取后存入字典列表,最后统一写入 CSV。encoding 用 utf-8-sig 是让 Excel 直接打开 CSV 时中文不乱码,这是很多人容易漏掉的细节。text split 处理只适合结构稳定的回显,如果设备回显格式不稳定,建议把原始回显存文件,CSV 里只放状态码。
参数说明:csv.DictWriter 的 fieldnames 顺序决定了 CSV 列的顺序。newline="" 是防止行与行之间出现空行,这个坑在 Windows 环境下最明显。
6.2 定时执行与失败重试
定时执行最常见的方式是系统自带的定时任务,Linux 里用 cron,Windows 里用任务计划程序。脚本本身保持可单次执行的状态,定时器只是到点把它拉起来。失败重试的逻辑放在脚本内部:
import time from netmiko import ConnectHandler def exec_with_retry(device, command, retries=3, interval=10): for attempt in range(1, retries + 1): try: conn = ConnectHandler(**device) output = conn.send_command(command) conn.disconnect() return output except Exception as e: print(f"第 {attempt} 次尝试失败: {e}") if attempt < retries: time.sleep(interval) raise RuntimeError(f"设备 {device['host']} 重试 {retries} 次后仍失败") device = { "device_type": "huawei", "host": "192.0.2.63", "username": "netadmin", "password": "your_password", } output = exec_with_retry(device, "display clock") print(output)逻辑说明:exec_with_retry 包装了连接和执行动作,失败后按设定的间隔重试。重试次数和间隔要根据场景调,巡检任务间隔一般比较长,重试间隔设 10 秒到 30 秒都没有问题;但如果是用户手动触发的脚本,重试间隔太长反而让人等得烦躁。
参数说明:interval 参数控制重试等待秒数,避免连续快速重试把设备连接数打满。这里有个细节,重试时要捕获的是连接层的异常,如果连接成功但命令执行报错,可能不需要重试,因为重试大概率得到同样的错误。
6.3 验证脚本的三种方式
脚本写完不是直接丢到生产环境跑,需要先验证。我的习惯是先用一台测试设备跑单条查询命令,确认连接参数、设备型号适配都没有问题。然后在模拟环境或者备用设备上执行批量任务,确认输出文件名、内容格式符合预期。最后在少量生产设备上小范围执行,观察设备 CPU 和管理通道的负载情况。
验证时要特意制造几个异常场景:密码错误、设备不可达、命令拼写错误,确认脚本能够捕获异常并给出清晰的错误信息。一个容易被忽视的检查点是脚本的退出码,定时任务依赖退出码判定任务成功还是失败,如果脚本内部处理了所有异常但没有把失败状态传递出去,定时任务会误以为一切正常。从那以后我每次把脚本交给定时任务之前,都会强制走一遍「正常执行、异常模拟、超时模拟」三组测试,确认退出码符合预期再放上去。希望帮到你。
本文还有配套的精品资源,点击获取