通过 Paramiko 读取 SSH stdout 在 REPL 和脚本之间表现不同

问题描述 投票:0回答:1

当我在 Python shell(REPL?)中时,我能够创建一个从 SSH 服务器的 stdout 读取的连接。但是当我运行与脚本相同的代码时(通过

python3 -i script.py
)它不起作用。

服务器端运行着一个基于文本的MUD。通过 SSH 登录后,它要求基于 MUD 的登录。

回复

最后你会看到 153 行的内容。

>>> import paramiko
>>> client = paramiko.SSHClient()
>>> client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
>>> client.connect(hostname='fakehost', username='fakeuser', password='fakepassword')
>>> shell = client.invoke_shell()
>>> shell.setblocking(0)
>>> shell.send('username\n')
8
>>> shell.send('password\n')
10
>>> f = shell.makefile('r')
>>> r = []
>>> while shell.recv_ready():
...     r.append(f.readline())
...
>>> print(f'Read {len(r)} lines.')
Read 153 lines.

作为剧本

#!/usr/bin/env python3
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname='fakehost', username='fakeuser', password='fakepassword')
shell = client.invoke_shell()
shell.setblocking(0)
shell.send('username\n')
shell.send('password\n')

f = shell.makefile('r')
r = []
while shell.recv_ready():
    r.append(f.readline())

print(f'Read {len(r)} lines.')

这里的输出就是

Read 1 lines.
。其他152行哪里去了?

python paramiko
1个回答
1
投票

如果第一次调用函数时没有任何可读取的内容,则立即退出循环。你需要先等待它准备好,然后你可以一直循环直到它不再准备好。

def get_output(shell: paramiko.channel.Channel) -> str:
    """Read from shell's stdout if data is available and return it as one string"""
    result = []

    while not shell.recv_ready():
        time.sleep(1)

    while shell.recv_ready():
        with shell.makefile('r') as stdout:
            time.sleep(.5)
            line = stdout.readline()

            line = ''.join(filter(
                lambda char: not char in ['\n', '\r'],
                line))

            line = line.strip()

            if line:
                result.append(line)

    return '\n'.join(result)
© www.soinside.com 2019 - 2024. All rights reserved.