首页 > 解决方案 > Netmiko read_channel() 和 Clear_buffer() 不打印输出

问题描述

因此,我试图自动将一些配置推送到我的交换机,但这些命令通常会在交换机中返回 (y/n) 提示。结果,send_command 函数在查找提示时将不起作用,因此我正在使用运行良好的 write_channel() 函数。但是,由于某种原因,在我发送命令后,read_channel 和 clear_buffer() 函数都不会打印超过 1 或 2 行的输出。

我尝试过的事情:
将 read_channel/buffer 置于慢循环中。
read_until_prompt/pattern
send_command 与 cmd_verify=False 和 auto_find_prompt=False
打印 read_channel
等等。. .

send_command 可以显示输出没有问题,它的源代码使用 read_channel() 来推送输出,所以我不确定还有什么可以尝试的。

目标:我需要从 cisco 交换机中的命令获取输出(在 001:00 重新加载),这样我就可以告诉程序如何对提示做出反应(如果有提示)。

这是我为解决主项目中的问题而编写的一些基本代码:

from netmiko import ConnectHandler
import time

Network_Device = {
                "ip": "10.251.11.38",
                "username": "user",
                "password": "pass",
                "secret": "secretpass",
                "device_type": "cisco_ios",
                "fast_cli": False
                }
        
#Connect = ConnectHandler(**Network_Device)

with ConnectHandler(**Network_Device) as ssh:
    ssh.enable()
    while True:
        x = input(ssh.find_prompt())
        if x == '':
            pass
        elif x == 'exit' or x == 'Exit':
            ssh.disconnect()
        else:
            ssh.write_channel(x) # Writes command to cli

            #Problem lies on the two functions below:  Neither will print out a show command fully.
            ssh.clear_buffer(backoff=True)
            ssh.read_channel()
    

    

标签: pythonsshnetmiko

解决方案


是的,我想几乎同时重新加载几十个交换机以进行 dhcp 更新。

现在很明显你想重新加载一堆开关。reload提示Proceed with reload? [confirm]您。因此,您可以使用expect_sting参数来确认或拒绝重新加载。为此,最好在重新加载之前先保存配置,以避免任何配置丢失。

简要介绍如何send_command工作。send_command基于模式的,它检查设备提示以了解命令输出是否完成。另一方面send_command_timing基于延迟的,这意味着它会等待一段时间并且不检查任何内容以了解命令是否已完成运行。

from netmiko import ConnectHandler

device = {
    "device_type": "",
    "ip": "",
    "username": "",
    "password": "",
    "secret": "",
    "conn_timeout": 12,
    "fast_cli": False,
}

conn = ConnectHandler(**device)

# Check if not logged into enable mode directly
# and enter enable mode if logged into user mode
if not conn.check_enable_mode():
    conn.enable()

conn.save_config()  # save configuration first
 
conn.send_command(command_string="reload", expect_string=r"confirm")

注意这里expect_string通知send_command我完成了。

现在您有以下两种选择之一:

  1. 发送y以确认重新加载(不鼓励)
  2. 调用conn.disconnect()以确认重新加载和退出(首选)

不鼓励使用选项 1,因为在确认重新加载后您将无法断开连接,并且最终会引发您必须处理的OSErroror异常。EOFError

conn.disconnect()

上面的行先发送一个\n,然后断开与设备的连接。这使您可以立即处理其他设备重新加载,而不必处理任何引发OSErrorEOFError异常。

完整示例

from netmiko import ConnectHandler

device = {
    "device_type": "",
    "ip": "",
    "username": "",
    "password": "",
    "secret": "",
    "conn_timeout": 12,
    "fast_cli": False,
}

conn = ConnectHandler(**device)

if not conn.check_enable_mode():
    conn.enable()

conn.save_config()

# Notice here the `expect_string` which informs 
# the `send_command` I am done. 
# I am telling `send_command` function don't look at 
# the device prompt but look for `"confirm"` to proceed 
# with the next command.
 
conn.send_command(command_string="reload", expect_string=r"confirm")

conn.disconnect()

print(f'Reloading {device["ip"]}... Please wait for some time for {device["ip"]} to boot up again')

我没有故意使用上下文管理器方法来利用conn.disconnect()函数。

更新

正如 Kirk Byers (netmiko 的作者)评论r"confirm"中推荐的那样,建议只添加expect_string并省略方括号。


推荐阅读