3. Netmiko命令执行模式

Netmiko 把“向设备发命令”这件事拆成了几个语义明确的入口,其中最常用的三个是 send_command()、send_config_set() 和 send_config_from_file()。它们并不是简单的别名,而是分别对应三种不同的会话状态与返回结构:执行态命令、配置态命令集、从文件批量下发配置。理解它们的差别,核心在于搞清楚“命令在哪个模式下执行”“返回的是回显文本还是配置结果”“失败时如何判断”。

一、send_command:执行态命令与回显文本

send_command() 用于在特权模式(privileged EXEC)或用户模式下执行查看类、诊断类命令,例如 show version、show ip interface brief、display interface。它不会进入配置模式,返回的是设备回显的字符串(str),而不是结构化数据。

from netmiko import ConnectHandler

device = {
    "device_type": "cisco_ios",
    "host": "192.0.2.10",
    "username": "admin",
    "password": "C1sco!23",
    "secret": "Enable!23",
}

with ConnectHandler(**device) as conn:
    conn.enable()                       # 进入特权模式
    out = conn.send_command("show ip interface brief")
    print(type(out))                    # <class 'str'>
    print(out)

返回结果处理的关键点有三个。第一,默认会做提示符匹配:Netmiko 发送命令后等待设备提示符再次出现,才认为命令执行完毕,因此返回内容通常不包含最后的提示符行。第二,分页处理:遇到 --More-- 时,Netmiko 默认会自动发送空格继续,若想关闭分页,可在命令中拼接 | no-more(华为/华三)或使用 terminal length 0(Cisco)。第三,超时与异常:命令执行时间超过 read_timeout(默认 10 秒)会抛出 ReadTimeout,此时应检查命令是否触发了交互式确认,或设备是否响应缓慢。

如果希望拿到结构化结果,可以配合 use_textfsm=True 或 use_genie=True,让 Netmiko 调用 TextFSM 模板或 Genie 解析器,把回显文本转成列表/字典。但要注意:模板不存在时不会报错,而是原样返回字符串,因此判断类型是必要的防御性写法。

二、send_config_set:配置态命令集

send_config_set() 接收一个命令列表,Netmiko 会自动进入配置模式(configure terminal 或 system-view),逐条下发,最后自动退出配置模式。它返回的是配置过程的回显文本,通常用于判断命令是否被接受。

config_commands = [
    "interface GigabitEthernet0/1",
    "description UPLINK-TO-CORE",
    "switchport mode trunk",
    "no shutdown",
]

with ConnectHandler(**device) as conn:
    conn.enable()
    result = conn.send_config_set(config_commands)
    print(result)

返回结果处理时,要重点关注两类信息:成功回显(如 %SYS-5-CONFIG_I: Configured from console)和错误回显(如 % Invalid input detected、% Incomplete command)。Netmiko 默认不会因为某条命令报错而中断,它会继续下发后续命令,因此必须通过字符串匹配来识别失败。一个实用的判断方式是:

error_markers = ["Invalid input", "Incomplete command", "Ambiguous command"]
if any(m in result for m in error_markers):
    raise RuntimeError("配置下发存在错误,请检查回显")

此外,send_config_set() 支持 cmd_verify 参数(默认 True),它会校验每条命令是否被设备回显,能更早发现命令被拒绝的情况;但在某些设备或慢速链路上,关闭它可以避免误判。另一个常用参数是 exit_config_mode=False,用于连续多次下发配置时保持配置模式,减少模式切换开销。

三、send_config_from_file:从文件批量下发

当配置量较大、需要版本化管理时,把配置写成文件再下发更合适。send_config_from_file() 读取本地文件内容,按行拆分成命令列表,然后复用 send_config_set() 的逻辑执行。它适合“一份配置模板对应多台设备”的场景。

with ConnectHandler(**device) as conn:
    conn.enable()
    result = conn.send_config_from_file("configs/edge_switch.cfg")
    print(result)

文件内容示例(configs/edge_switch.cfg):

interface GigabitEthernet0/2
 description ACCESS-PC
 switchport mode access
 switchport access vlan 20
 spanning-tree portfast
!

返回结果的处理方式与 send_config_set() 完全一致,因为底层是同一套逻辑。需要额外注意的是:文件中的空行和注释行(以 ! 或 # 开头)会被 Netmiko 过滤或原样发送,具体行为取决于设备类型;建议在文件里保持与设备 CLI 一致的写法,避免混入非命令文本。另外,文件路径是相对于当前工作目录的,工程中建议使用绝对路径或基于 pathlib 拼接,避免因执行目录不同而找不到文件。

四、三种模式的对比与选择

下面这张图把三种命令执行模式放在同一条会话链路上,标出了它们所处的模式、输入形态和返回结果类型,便于快速对照。

Netmiko 三种命令执行模式:模式 · 输入 · 返回 ConnectHandler 建立 SSH 会话 模式判断 EXEC / CONFIG send_command() EXEC 模式 · 单条命令 show / display 类 send_config_set() CONFIG 模式 · 命令列表 自动进入/退出配置模式 send_config_from_file() CONFIG 模式 · 文件读取 按行拆分为命令列表 返回 str 设备回显文本 可 TextFSM 解析 返回 str 配置过程回显 需匹配错误关键字 返回 str 同 send_config_set 文件路径需正确 结果处理要点: send_command 关注提示符与分页;send_config_set / send_config_from_file 关注 Invalid input、Incomplete command 等错误回显,必要时用 cmd_verify 提前拦截。

五、返回结果处理的通用实践

无论使用哪一种模式,返回结果处理都应遵循“先判断类型,再判断内容,最后决定是否重试”的顺序。对于 send_command(),如果期望结构化数据,先确认 use_textfsm 是否真的命中了模板;对于配置类命令,建议把错误关键字匹配封装成统一函数,避免每处重复写判断。同时,read_timeout 和 cmd_verify 应根据设备响应速度调整:慢速设备适当增大超时,快速设备可保持默认校验。

在批量运维脚本中,推荐把 send_config_set() 与 send_config_from_file() 的返回结果统一收集到日志文件,并记录设备 IP、时间戳和错误关键字命中情况,便于事后审计与回滚定位。
不要用 send_command() 去执行配置命令。虽然某些设备在特权模式下也能接受部分配置命令,但 Netmiko 不会自动进入配置模式,命令可能被拒绝或产生非预期行为。配置类操作应始终使用 send_config_set() 或 send_config_from_file()。