You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Netmiko配置备份:如何忽略认证/超时等异常并完成设备遍历

使用Netmiko批量备份设备时,遇到认证/连接异常如何让脚本继续执行?

这是我首次在Stack Overflow提问,之前靠这个平台快速入门了脚本开发,但现在碰到个棘手问题:用Netmiko批量备份设备配置时,只要遇到认证失败、连接超时、连接拒绝这类异常,脚本就直接中断,没法遍历完所有设备。我需要修改代码,让脚本忽略这些异常,继续处理后续设备的备份。

我的代码

# SSH to Multiple Devices from devices file
import csv
import logging
from netmiko import ConnectHandler
from netmiko import ConnLogOnly
from getpass import getpass
import paramiko.ssh_exception
import netmiko.exceptions
from netmiko.exceptions import NetMikoTimeoutException
from netmiko.exceptions import NetMikoAuthenticationException
from paramiko.ssh_exception import AuthenticationException

log_level = logging.INFO
log_file = "backup_script.log"
host_list = input('Enter /path/to/filename of CSV file: ')
uname = input('Enter username: ')
passwd = getpass()
with open(host_list, mode='r') as file:
    reader = csv.DictReader(file)
    devices = [row for row in reader]

    for device in devices:
        try:
            connection = ConnectHandler(
                device_type=device['device_type'],
                host=device['hostname'],
                username=(uname),
                password=(passwd)
            )
        except NetMikoTimeoutException:
            print("Connection timed out, trying again...")
        except NetMikoAuthenticationException:
            print("Authentication failed, please check credentials.")
        except Exception as e:
            print(f"An unexpected error occurred: {str(e)}")
        connection = ConnectHandler(
            device_type=device['device_type'],
            host=device['hostname'],
            username=(uname),
            password=(passwd)
        )
        filename = (f"backup_testing/{device['hostname']}-running-config")
        connection.send_command('term len 0')
        showrun = connection.send_command('show run')
        log_file1 = open(filename, "a")   # in append mode
        log_file1.write(showrun)
        log_file1.write(showrun)
        log_file1.write("\n")
        connection.disconnect()
        print(f"{device['hostname']} Done!")

执行报错输出

python3.11 backup-multiple-routers-csv-input-file-with-logging.py
Enter /path/to/filename of CSV file: test_backup_list.csv
Enter username: adm_teagumi1
Password:
Authentication failed, please check credentials.
Traceback (most recent call last):
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/netmiko/base_connection.py", line 1142, in establish_connection
    self.remote_conn_pre.connect(**ssh_connect_params)
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/paramiko/client.py", line 485, in connect
    self._auth(
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/paramiko/client.py", line 818, in _auth
    raise saved_exception
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/paramiko/client.py", line 805, in _auth
    self._transport.auth_password(username, password)
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/paramiko/transport.py", line 1638, in auth_password
    return self.auth_handler.wait_for_response(my_event)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/paramiko/auth_handler.py", line 263, in wait_for_response
    raise e
paramiko.ssh_exception.AuthenticationException: Authentication failed.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/adm_teagumi1/backup-multiple-routers-csv-input-file-with-logging.py", line 36, in <module>
    connection = ConnectHandler(
                 ^^^^^^^^^^^^^^^
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/netmiko/ssh_dispatcher.py", line 410, in ConnectHandler
    return ConnectionClass(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/netmiko/base_connection.py", line 493, in __init__
    self._open()
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/netmiko/base_connection.py", line 498, in _open
    self.establish_connection()
  File "/home/adm_teagumi1/.local/lib/python3.11/site-packages/netmiko/base_connection.py", line 1179, in establish_connection
    raise NetmikoAuthenticationException(msg)
netmiko.exceptions.NetMikoAuthenticationException: Authentication to device failed.

问题常见原因

  • 用户名或密码无效
  • SSH密钥文件错误
  • 连接到错误的设备

设备配置:cisco_ios USFW-NDC-LAB-MGMT-A02:22,认证失败。


解决方案

你的代码核心问题是异常处理范围太小,而且在捕获异常后又重复调用了ConnectHandler,导致异常再次抛出中断脚本。正确的做法是把当前设备的所有操作(连接、备份、断开)都放到try块里,捕获异常后直接跳过当前设备,继续处理下一个。

修改后的代码如下:

# SSH to Multiple Devices from devices file
import csv
import logging
from netmiko import ConnectHandler
from getpass import getpass
from netmiko.exceptions import NetMikoTimeoutException, NetMikoAuthenticationException

# 初始化日志
logging.basicConfig(
    filename="backup_script.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

host_list = input('输入CSV文件路径: ')
uname = input('输入用户名: ')
passwd = getpass()

with open(host_list, mode='r') as file:
    reader = csv.DictReader(file)
    devices = list(reader)

for device in devices:
    hostname = device['hostname']
    try:
        # 建立连接
        connection = ConnectHandler(
            device_type=device['device_type'],
            host=hostname,
            username=uname,
            password=passwd
        )
        logging.info(f"成功连接到 {hostname}")
        
        # 获取配置
        connection.send_command('term len 0')
        showrun = connection.send_command('show run')
        
        # 保存配置(用with自动关闭文件)
        filename = f"backup_testing/{hostname}-running-config"
        with open(filename, "w") as log_file1:  # 用w模式覆盖旧备份,a是追加可根据需求调整
            log_file1.write(showrun)
            log_file1.write("\n")
        
        # 断开连接
        connection.disconnect()
        print(f"{hostname} 备份完成!")
        logging.info(f"{hostname} 备份已保存")

    except NetMikoTimeoutException:
        error_msg = f"{hostname} 连接超时"
        print(error_msg)
        logging.error(error_msg)
        continue  # 跳过当前设备,继续下一个
    except NetMikoAuthenticationException:
        error_msg = f"{hostname} 认证失败,请检查凭据"
        print(error_msg)
        logging.error(error_msg)
        continue
    except Exception as e:
        error_msg = f"{hostname} 发生意外错误: {str(e)}"
        print(error_msg)
        logging.error(error_msg)
        continue

关键改动说明

  1. 扩大try块范围:把连接、备份、断开操作都放到try里,确保任何步骤出错都能被捕获
  2. 移除重复的ConnectHandler调用:原来的代码在捕获异常后又重新调用一次,直接导致异常再次抛出
  3. 添加continue语句:捕获异常后跳过当前设备,继续遍历下一个
  4. 优化文件操作:用with open自动管理文件,避免忘记关闭
  5. 完善日志记录:把错误信息同时记录到日志文件,方便后续排查
  6. 简化导入:去掉没用的导入语句,让代码更简洁

内容的提问来源于stack exchange,提问作者olddude

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 10:14:51