Administrator
发布于 2026-05-28 / 11 阅读
0
0

Parmiko操作华为设备

本文开发环境为 Python 3.10 解释器、Paramiko 3.4.x 版本,适配华为 VRP V5 系统设备。

Paramiko 是 Python 生态中最底层的 SSH2 协议实现,纯 Python 编写,不依赖任何第三方二进制库,跨平台兼容性极强。但它不懂华为 VRP 系统的提示符规则,不会自动处理 ---- More ---- 分页,也不会帮你切换配置模式,所有交互逻辑都需要你自己用代码精确控制。Paramiko 的 SSHClient 实现了上下文管理器协议,配合 with 语句可以自动管理连接生命周期,避免 VTY 线路泄漏。这一篇就带你从零手搓一个能稳定对接华为设备的 Paramiko 封装。

基础连接与命令执行

Paramiko 建立 SSH 连接只需要 IP、用户名和密码(或密钥),但它不会自动识别设备提示符,也不会自动关闭分页。这意味着你发送 display version 后,必须自己判断输出何时结束、是否需要按空格翻页。下面这张表列出了最核心的四个方法,每个都标注了华为场景下的注意事项。

功能名称

实例调用方法

具体功能与注意事项

创建SSH客户端

paramiko.SSHClient()

返回客户端实例,需先设置主机密钥策略才能连接未知主机

建立连接

client.connect(hostname, username, password)

支持密码和私钥认证,timeout参数控制TCP握手超时

执行命令

client.exec_command(command)

返回stdin/stdout/stderr三元组,stdout需read()读取且为bytes类型

自动释放连接

with paramiko.SSHClient() as client:

退出with块时自动调用close(),无需手动断开

下面是使用 with 语句连接华为设备并执行命令的完整示例,每行都有注释说明数据流向:

import paramiko  # 导入Paramiko核心模块

try:
    # with语句创建SSH客户端,退出代码块时自动关闭连接
    with paramiko.SSHClient() as client:
        # 允许连接未知主机,生产环境建议加载known_hosts
        # AutoAddPolicy自动接受并保存主机密钥,首次连接不会报错
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        # 建立SSH连接到华为VRP V5设备
        # timeout控制TCP握手超时,banner_timeout控制等待SSH横幅超时
        client.connect(
            hostname="192.168.1.1",   # 华为设备管理IP
            port=22,                   # SSH端口
            username="admin",          # 登录用户名
            password="Admin@123",      # 登录密码
            timeout=30,                # TCP连接超时秒数
            banner_timeout=30          # 等待SSH Banner超时秒数
        )

        # exec_command返回三元组:标准输入、标准输出、标准错误
        # 注意:返回的是Channel对象,不是字符串
        stdin, stdout, stderr = client.exec_command("display version")

        # read()返回bytes类型,必须decode转为字符串
        # 此处未处理分页,若输出超过一屏会被截断或阻塞
        output = stdout.read().decode("utf-8")
        error = stderr.read().decode("utf-8")

        print(output)
        if error:
            print(f"错误信息: {error}")

except paramiko.AuthenticationException as e:
    # 用户名或密码错误
    print(f"认证失败: {e}")
except paramiko.SSHException as e:
    # SSH协议层错误,如主机密钥验证失败
    print(f"SSH异常: {e}")
except Exception as e:
    # 兜底捕获网络不可达等其他异常
    print(f"未知错误: {e}")
# with块结束,SSH连接已自动关闭,无需额外清理

这一节讲了用 with 语句管理 Paramiko 连接的基础流程,你会发现它比 Netmiko 多了不少"手工活",但也因此获得了完全的控制权。

交互式Shell与分页处理

exec_command 适合单条无交互命令,但华为 VRP V5 设备的 display 命令经常触发 ---- More ---- 分页,而且配置模式需要通过 system-view 进入、return 退出,这些都需要一个持久的交互式 Shell 会话。Paramiko 的 invoke_shell() 方法返回一个 Channel 对象,你可以像操作终端一样持续收发数据,但代价是所有提示符匹配和分页处理都得自己写。

功能名称

实例调用方法

具体功能与注意事项

打开交互式Shell

client.invoke_shell(width, height)

返回Channel对象,width/height控制终端尺寸影响分页行为

发送数据

channel.send(data)

参数必须是bytes或str,发送命令后需加\n换行符

接收数据

channel.recv(nbytes)

返回bytes,可能一次收不全,需循环读取直到提示符出现

检测可读状态

channel.recv_ready()

返回布尔值,判断缓冲区是否有待读数据,避免recv阻塞

关闭Shell

channel.close()

主动关闭Channel,with语句只关client不关channel

下面是通过交互式 Shell 处理华为 VRP V5 分页和配置模式的完整示例:

import time       # 用于等待设备响应
import paramiko   # 导入Paramiko核心模块

def wait_for_prompt(channel, prompt, timeout=10):
    """循环读取直到匹配到期望提示符或超时"""
    buffer = ""              # 累积接收到的输出内容
    start_time = time.time() # 记录开始时间用于超时判断
    while True:
        # 检查缓冲区是否有新数据到达
        if channel.recv_ready():
            # 每次最多读取4096字节,decode后追加到buffer
            chunk = channel.recv(4096).decode("utf-8", errors="ignore")
            buffer += chunk
            # 检查是否匹配到目标提示符
            if prompt in buffer:
                return buffer
        # 超时保护,防止设备无响应导致死循环
        if time.time() - start_time > timeout:
            raise TimeoutError(f"等待提示符'{prompt}'超时")
        # 短暂休眠避免CPU空转
        time.sleep(0.1)

try:
    # with管理SSH客户端生命周期
    with paramiko.SSHClient() as client:
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(
            hostname="192.168.1.1",
            username="admin",
            password="Admin@123",
            timeout=30
        )

        # 打开交互式Shell,设置终端尺寸避免默认分页
        # width=200让单行显示更多内容,减少分页触发概率
        channel = client.invoke_shell(width=200, height=50)

        # 等待登录后的用户视图提示符 <Huawei>
        login_output = wait_for_prompt(channel, ">")
        print(login_output)

        # 关闭分页,VRP V5使用screen-length 0 temporary
        # 发送命令必须带\n换行符,否则设备不会执行
        channel.send("screen-length 0 temporary\n")
        wait_for_prompt(channel, ">")

        # 进入系统视图,VRP V5使用system-view命令
        channel.send("system-view\n")
        # 等待配置视图提示符 [Huawei]
        config_output = wait_for_prompt(channel, "]")
        print(config_output)

        # 执行配置命令
        channel.send("vlan 100\n")
        wait_for_prompt(channel, "]")

        # 退出配置模式回到用户视图
        channel.send("return\n")
        wait_for_prompt(channel, ">")

        # 手动关闭Channel,with只负责关闭client
        channel.close()

except Exception as e:
    print(f"交互失败: {e}")
# with块结束,SSH连接自动释放

这一节讲了如何用 Paramiko 交互式 Shell 应对华为 VRP V5 的分页和模式切换,虽然代码量比 Netmiko 多,但你完全掌控了每一个交互细节。

注意事项与返回值处理

Paramiko 是把锋利的手术刀,用好了精准无比,用不好容易伤到自己。把这些注意事项记牢,能让你少踩很多弯路。

  • 优先使用 with 语句管理连接with 利用 Python 上下文管理器协议保证 SSHClient 一定被关闭,手动调用 close() 容易在异常分支中被跳过。但要注意 with 只管 Client 不管 Channel,交互式 Shell 的 Channel 必须手动关闭。

  • VRP V5 分页命令是 screen-length 0 temporary:不要写成 terminal length 0(那是思科),也不要写成 screen-length disable(部分新版本才支持)。这条命令必须在每条长输出命令前执行,或者在会话开始时统一执行一次。

  • exec_command 与 invoke_shell 不要混用:同一个连接里先用 exec_command 再开 invoke_shell 可能导致通道冲突。如果要做交互式操作,全程只用 invoke_shell;如果只是跑几条简单查询,全程只用 exec_command

  • recv 返回 bytes 必须 decode:Paramiko 所有收发都是字节流,忘记 decode 会导致字符串匹配永远失败。建议统一用 utf-8 编码,加 errors="ignore" 防止个别乱码字符导致解码崩溃。

  • 提示符匹配要足够精确:VRP V5 用户视图是 <Hostname>,配置视图是 [Hostname],接口视图是 [Hostname-GigabitEthernet0/0/1]。用 > 匹配用户视图时注意排除配置视图中可能出现的 > 字符,建议用正则或更长的子串匹配。

  • send 发送的命令必须以 \n 结尾:Paramiko 不会自动补换行符,漏掉 \n 设备会一直等你输入,直到超时。这不是 bug,是底层协议的忠实还原。

  • 异常处理要分层AuthenticationException 对应账号密码问题,SSHException 对应协议层问题,socket.timeout 对应网络问题。不要用一个笼统的 except Exception 吞掉所有异常,否则出了问题无法快速定位原因。

  • 并发连接要克制:华为 VRP V5 设备的 VTY 线路默认只有 5 条,同时开太多连接会把设备打满导致后续 Telnet/SSH 全部拒绝。建议使用线程池控制并发数,每个并发任务都应使用独立的 with 块管理自己的连接生命周期。

Paramiko 给了你最底层的控制权,也意味着你要承担最多的责任。把基础打牢,把细节抠到位,你就能用它搞定那些 Netmiko 搞不定的奇葩设备和非标场景,当然大多数正常情况下,推荐用Netmiko库。


评论