当我在 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行哪里去了?
如果第一次调用函数时没有任何可读取的内容,则立即退出循环。你需要先等待它准备好,然后你可以一直循环直到它不再准备好。
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)