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

使用Paramiko+CiscoConfParse读远程配置及Rancid脚本技术咨询

嘿,我来帮你搞定这两个需求——先说说怎么用Paramiko搭配CiscoConfParse读取远程思科设备的配置,再把你那套和Rancid交互的脚本补全优化一下~

一、用Paramiko + CiscoConfParse读取远程思科配置

这个思路很清晰:先用Paramiko建立SSH连接到设备,拉取完整配置(比如show running-config),再把配置内容传给CiscoConfParse做结构化解析,不用自己写一堆正则来处理配置层级。

完整示例代码

import paramiko
from ciscoconfparse import CiscoConfParse

def get_and_parse_cisco_config(device_ip, username, password):
    # 1. 初始化SSH客户端并建立连接
    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        ssh_client.connect(
            hostname=device_ip,
            username=username,
            password=password,
            look_for_keys=False,
            allow_agent=False
        )
        
        # 2. 执行命令获取设备配置
        stdin, stdout, stderr = ssh_client.exec_command("show running-config")
        config_output = stdout.read().decode('utf-8')
        
        # 检查是否有错误输出
        error_msg = stderr.read().decode('utf-8')
        if error_msg:
            print(f"获取配置时出错: {error_msg}")
            return None
        
        # 3. 用CiscoConfParse解析配置内容
        parsed_config = CiscoConfParse(config_output.splitlines())
        return parsed_config
    
    except Exception as e:
        print(f"连接或执行命令失败: {str(e)}")
        return None
    finally:
        # 确保SSH连接被关闭,避免资源泄漏
        if ssh_client.get_transport() and ssh_client.get_transport().is_active():
            ssh_client.close()

# 调用示例
if __name__ == "__main__":
    config = get_and_parse_cisco_config("192.168.1.1", "admin", "your_password")
    if config:
        # 举个实用例子:提取所有access模式接口及其所属VLAN
        access_intfs = config.find_objects_w_child(
            parentspec=r'^interface',
            childspec=r'switchport mode access'
        )
        for intf in access_intfs:
            vlan_match = intf.re_search_children(r'switchport access vlan (\d+)')
            if vlan_match:
                print(f"接口 {intf.text.strip()} 属于VLAN {vlan_match[0].group(1)}")

关键细节提醒

  • 加上look_for_keys=False和allow_agent=False可以跳过本地密钥和代理的自动尝试,适合纯密码登录的场景
  • CiscoConfParse会自动识别思科配置的层级结构,你可以用它的find_objects、re_search_children等方法快速定位配置项,比自己写正则高效太多
二、完善你的Rancid VLAN查询脚本

看你已经写了个雏形,我帮你补全逻辑、加上异常处理和资源清理,让脚本更健壮:

import paramiko

def get_vlans():
    # 这里是你调用IPAM API获取新VLAN的逻辑,示例返回VLAN ID列表
    return [100, 200, 300]

def check_rancid_for_vlan(rancid_host, username, password):
    vlans = get_vlans()
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    results = {}
    
    try:
        client.connect(
            rancid_host,
            username=username,
            password=password,
            look_for_keys=False,
            allow_agent=False
        )
        
        for vlan_id in vlans:
            # 执行Rancid的device q命令
            cmd = f"device q {vlan_id}"
            stdin, stdout, stderr = client.exec_command(cmd)
            
            # 读取命令输出和错误信息
            output = stdout.read().decode('utf-8').strip()
            error = stderr.read().decode('utf-8').strip()
            
            if error:
                results[vlan_id] = {"status": "error", "message": error}
            else:
                # 根据Rancid实际输出格式解析设备信息,这里是示例逻辑
                device_info = {}
                if output:
                    for line in output.splitlines():
                        if "Device Name:" in line:
                            device_info["name"] = line.split("Device Name:")[1].strip()
                        if "Device IP:" in line:
                            device_info["ip"] = line.split("Device IP:")[1].strip()
                results[vlan_id] = device_info if device_info else {"status": "no_matching_devices"}
                
    except Exception as e:
        print(f"连接Rancid服务器失败: {str(e)}")
        # 给所有VLAN标记连接失败状态
        for vlan_id in vlans:
            results[vlan_id] = {"status": "connection_failed", "message": str(e)}
    finally:
        # 确保关闭SSH连接
        if client.get_transport() and client.get_transport().is_active():
            client.close()
    
    return results

# 调用示例
if __name__ == "__main__":
    rancid_results = check_rancid_for_vlan("rancid-server-ip", "rancid-user", "rancid-pass")
    for vlan, info in rancid_results.items():
        print(f"VLAN {vlan}: {info}")

优化点说明

  • 用try/finally块确保不管有没有异常,SSH连接都会被关闭,避免资源泄漏
  • 给每个VLAN的查询结果添加了状态标记,方便后续处理错误场景
  • 解析Rancid输出的部分需要你根据device q命令的实际输出格式调整,比如如果输出是JSON或者特定分隔符格式,要对应修改解析逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:14:02