首页 > 解决方案 > 使用 paramiko 从 windows openssh 服务器读取 9999 行后,具有 channel.recv 的 PipeTimeout

问题描述

我正在尝试使用 paramiko 运行多个命令。从服务器读取 9999 行后恰好Channel.recv引发。paramiko.buffered_pipe.PipeTimeout

我正在使用从 linux 安装的 openssh 连接到远程 Windows 服务器 2012。Windows 服务器的输出有ANSI sequencesH代码,所以我可以看到Channel.recv在读取 9999 行后等待超时。Channel.recv(buffer_size)在此输出后等待超时b'\x1b[9999;54H'(9999 行,54 列)。

这是我最小的可重现示例:

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=hostname, username=username, password=password)

interact = SSHClientInteraction(client, timeout=60, display=True, buffer_size=65535, tty_width=100, tty_height=24)
interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)

interact.send('dir')
interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)
cmd_output_dir = interact.current_output_clean

for i in range(100):
    interact.send('ipconfig')
    interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)
    cmd_output_dir = interact.current_output_clean

    interact.send('ipconfig')
    interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)
    cmd_output_dir = interact.current_output_clean

    interact.send('dir')
    interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)
    cmd_output_dir = interact.current_output_clean

    interact.send('dir')
    interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)
    cmd_output_dir = interact.current_output_clean

    interact.send('ipconfig')
    interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)
    cmd_output_dir = interact.current_output_clean

    interact.send('ipconfig')
    interact.expect(r".*C:\\Users\\Administrator>.*", strip_ansi=False)
    cmd_output_dir = interact.current_output_clean

我看到paramiko_expect读取可用数据,直到收到的输出与Channel.recv. 因此,问题可能不在于读取大输出。可能是服务器的数据可用性有问题吗?谁能帮我解决这个问题?

编辑 我试图在不使用 paramiko_expect 的情况下重现这个问题。我仍然可以看到同样的问题。在获取之前PipeTimeout,我看到命令的输出不完整。这是代码:

re_strings = [r".*C:\\Users\\Administrator>.*", ".*Command:.*"]
default_match_prefix = ".*\n"

# Use SSH client to login
# Create a new SSH client object
client = paramiko.SSHClient()

# Set SSH key parameters to auto accept unknown hosts
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# Connect to the host
client.connect(hostname=hostname, username=username, password=password)
client.get_transport().window_size = 3 * 1024 * 1024 * 1024
channel = client.invoke_shell(width=100, height=24)
channel.settimeout(10800)
channel.set_combine_stderr(True)

for i in range(100):
    for cmd in ['ipconfig', 'ipconfig', 'dir', 'dir', 'ipconfig', 'ipconfig', 'ipconfig']:
        # import time
        # time.sleep(1)
        channel.send(cmd + "\r")

        # Create an empty output buffer
        current_output = ''

        # Loop until one of the expressions is matched or loop forever if
        # nothing is expected (usually used for exit)
        while (not [re_string for re_string in re_strings
                    if re.match(default_match_prefix + re_string + '$', current_output, re.DOTALL)]):

            # # Read some of the output
            current_output += channel.recv(len(channel.in_buffer)).decode('utf-8')

            # If we have an empty buffer, then the SSH session has been closed
            if len(current_output) == 0:
                break

标签: windowspython-3.6paramikoopenssh

解决方案


推荐阅读