Netmiko 网络自动化指南

github.com 于 2025-12-19 发布

Netmiko 简介

Netmiko 通过提供统一的界面来管理来自不同厂商的设备,从而简化了对网络设备的 SSH 管理。

主要用途


安装 Netmiko

Netmiko 不是 Python 标准库的一部分,需要使用 pip 进行安装:

pip install netmiko

Netmiko 会自动安装以下依赖项:Paramiko、scp、pyserial 和 textfsm。

验证安装:在 Python shell 中导入测试

import netmiko

基础连接

连接单个设备

from netmiko import ConnectHandler

connection = ConnectHandler(
    host="172.16.10.12",
    username="admin",
    password="cisco",
    device_type="cisco_ios"
)

output = connection.send_command("show ip interface brief")
print(output)

connection.disconnect()

输出示例

Interface                  IP-Address      OK? Method Status                Protocol
FastEthernet0/0            172.16.10.12    YES NVRAM  up                    up      
FastEthernet0/1            unassigned      YES NVRAM  administratively down down    
Loopback0                  1.1.1.0         YES manual up                    up      
Loopback2                  1.1.1.2         YES manual up                    up

重要提示

  1. 确保 Cisco 设备已正确配置 SSH 访问
  2. Python 工作站可以成功通过 SSH 连接到该设备
  3. 务必使用 disconnect() 方法断开 SSH 会话

使用字典管理设备信息

为什么使用字典?

使用 Python 字典可以让设备信息更有序、更易于管理和重复使用。

基本用法

from netmiko import ConnectHandler

# 定义设备信息
SW_01 = {
    "device_type": "cisco_ios",
    "host": "172.16.10.12",
    "username": "admin",
    "password": "cisco"
}

# 使用字典解包连接设备
connection = ConnectHandler(**SW_01)

# 执行命令
output = connection.send_command('show interface desc')
print(output)

# 断开连接
connection.disconnect()

输出示例

Interface                      Status         Protocol Description
Fa0/0                          up             up       
Fa0/1                          admin down     down

启用特权 EXEC 模式

为什么需要特权模式?

某些命令(如 show run)需要更高的权限才能执行。

实现方法

from netmiko import ConnectHandler

SW_01 = {
    "device_type": "cisco_ios",
    "host": "172.16.10.12",
    "username": "admin",
    "password": "cisco",
    "secret": "cisco123"  # Enable 密码
}

connection = ConnectHandler(**SW_01)

# 进入特权模式
connection.enable()

# 验证当前模式
device_prompt = connection.find_prompt()
print(device_prompt)  # 应显示 '#' 提示符

# 执行需要特权的命令
output = connection.send_command('show run')
print(output)

connection.disconnect()

设备配置

进入全局配置模式

from netmiko import ConnectHandler

SW_01 = {
    "device_type": "cisco_ios",
    "host": "172.16.10.11",
    "username": "admin",
    "password": "cisco",
    "secret": "cisco123"
}

connection = ConnectHandler(**SW_01)
connection.enable()

# 进入全局配置模式
connection.config_mode()

# 执行配置命令
connection.send_command('access-list 1 permit any')

# 退出全局配置模式
connection.exit_config_mode()

# 验证配置
show_output = connection.send_command('show interface desc')
print(show_output)

connection.disconnect()

安全处理密码

使用 getpass 保护密码

为什么要用 getpass?

from netmiko import ConnectHandler
import getpass

# 安全地提示用户输入密码
passwd = getpass.getpass('Please enter the password: ')

SW_01 = {
    "device_type": "cisco_ios",
    "host": "172.16.10.11",
    "username": "admin",
    "password": passwd,
    "secret": passwd
}

connection = ConnectHandler(**SW_01)
connection.enable()

output = connection.send_command('show interface desc')
print(output)

connection.disconnect()

发送多个命令

使用 send_config_set 方法

这个方法可以一次性发送多个配置命令,自动处理进入和退出配置模式。

from netmiko import ConnectHandler
import getpass

passwd = getpass.getpass('Please enter the password: ')

SW_01 = {
    "device_type": "cisco_ios",
    "host": "172.16.10.11",
    "username": "admin",
    "password": passwd,
    "secret": passwd
}

connection = ConnectHandler(**SW_01)
connection.enable()

# 定义配置命令列表
config_commands = [
    'interface gi0/0',
    'description WAN',
    'exit',
    'access-list 1 permit any'
]

# 批量发送配置命令
connection.send_config_set(config_commands)

# 验证配置
print(connection.send_command('show interfaces description'))
print(connection.send_command('show access-lists'))

connection.disconnect()

连接多个设备

批量管理设备

from netmiko import ConnectHandler
import getpass
import json

passwd = getpass.getpass('Please enter the password: ')

# 设备 IP 列表
ip_list = ["172.16.10.11", "172.16.10.12"]

# 创建设备列表
device_list = []

for ip in ip_list:
    device = {
        "device_type": "cisco_ios",
        "host": ip,
        "username": "admin",
        "password": passwd,
        "secret": passwd
    }
    device_list.append(device)

# 打印设备列表(格式化输出)
json_formatted = json.dumps(device_list, indent=4)
print(json_formatted)

# 遍历并连接每个设备
for each_device in device_list:
    connection = ConnectHandler(**each_device)
    connection.enable()
    
    print(f'Connecting to {each_device["host"]}')
    output = connection.send_command('show run | incl hostname')
    print(output)
    
    print(f'Closing Connection on {each_device["host"]}')
    connection.disconnect()

高级配置管理

向多个设备发送配置

from netmiko import ConnectHandler

# 定义多个设备
devices = [
    {
        'device_type': 'cisco_ios',
        'ip': '172.16.10.11',
        'username': 'admin',
        'password': 'cisco',
        'secret': 'cisco123',
    },
    {
        'device_type': 'cisco_ios',
        'ip': '172.16.10.12',
        'username': 'admin',
        'password': 'cisco',
        'secret': 'cisco123',
    },
]

# 遍历设备并配置
for device in devices:
    print(f"Connecting to {device['ip']}...")
    net_connect = ConnectHandler(**device)
    net_connect.enable()

    # 配置设备
    config_commands = ['username admin pri 15 password cisco']
    net_connect.send_config_set(config_commands)
    net_connect.save_config()

    # 显示更新后的配置
    output = net_connect.send_command('show running-config | section username')
    print(output)

    print(f'Closing Connection on {device["ip"]}')
    net_connect.disconnect()

从文件应用配置

from netmiko import ConnectHandler

device = {
    'device_type': 'cisco_ios',
    'ip': '172.16.10.11',
    'username': 'admin',
    'password': 'cisco',
    'secret': 'cisco123',
}

file = "config_file.cfg"

# 使用上下文管理器
with ConnectHandler(**device) as net_connect:
    output = net_connect.send_config_from_file(file)
    output += net_connect.save_config()

print(output)

异常处理

处理常见错误

在网络自动化中,异常处理至关重要,可以优雅地处理超时和认证失败等问题。

from netmiko import ConnectHandler
from netmiko.ssh_exception import NetmikoTimeoutException, NetmikoAuthenticationException

devices = [
    {
        'device_type': 'cisco_ios',
        'ip': '172.16.10.11',
        'username': 'admin',
        'password': 'cisco123',  # 错误的密码
    },
    {
        'device_type': 'cisco_ios',
        'ip': '172.16.10.12',  # 错误的 IP
        'username': 'admin',
        'password': 'cisco',
    }
]

# 尝试连接并处理异常
for device in devices:
    try:
        net_connect = ConnectHandler(**device)
        output = net_connect.send_command("show ip int brief")
        print(output)
    except NetmikoTimeoutException:
        print(f"Device {device['ip']} not reachable")
    except NetmikoAuthenticationException:
        print(f"Authentication failed for {device['ip']}")

备份设备配置

自动化配置备份

from netmiko import ConnectHandler
from datetime import datetime

devices = [
    {
        "host": "172.16.10.11",
        "username": "admin",
        "password": "cisco",
        "device_type": "cisco_ios",
    },
    {
        "host": "172.16.10.12",
        "username": "admin",
        "password": "cisco",
        "device_type": "cisco_ios",
    }
]

# 获取当前时间戳
time_stamp = datetime.now().strftime("%d-%b-%Y")

# 备份每个设备的配置
for device in devices:
    net_connect = ConnectHandler(**device)
    print(f"Initiating running config backup for {device['host']}...")
    
    sh_run = net_connect.send_command('show run')

    # 保存到文件
    with open(f"{device['host']}_{time_stamp}.cfg", 'w') as f:
        f.write(sh_run)
        print("Backup saved")

print("Finished backup process.")

总结

Netmiko 的主要优势:

通过掌握 Netmiko,网络工程师可以显著提高网络管理效率,实现配置自动化和标准化。


参考资源

原文转载:https://python-automation-book.readthedocs.io/en/1.0/12_netmiko/01_netmiko.html#sending-multiple-commands