paramiko python模块挂在stdout.read()

时间:2016-02-08 09:59:48

标签: python python-3.x paramiko python-module

我使用以下代码:

import paramiko

def runSshCmd(hostname, username, password, cmd, timeout=None):          
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(hostname, username=username, password=password,
            allow_agent=False, look_for_keys=False, timeout=timeout) 
    stdin, stdout, stderr = client.exec_command(cmd)
    stdin.flush()
    data = stdout.read()
    print (data)
    client.close()

runSshCmd("10.128.12.32", "root", "C0mput3Gr!d", "ts_menu")

当谈到stdout.read()时,它会挂起......有时会在很长时间后打印输出。

请问你能否就这个问题做些什么呢?

我在以下情况中看到了这个问题:

https://bugs.python.org/issue24026

在python中是否有更好的模块用于ssh连接和运行命令??

5 个答案:

答案 0 :(得分:12)

可能与https://github.com/paramiko/paramiko/issues/109

有关

下面解释我面临的问题以及我是如何解决这个问题的。

我也遇到了这个问题     stdout.channel.eof_received == 0

>>> print stdin
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
>>> print stdout
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
>>> print stderr
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
stdin,stdout和stderr保持开放......

>>> print stdin.channel.eof_received
0

因此未收到EOF ......

>>> timeout = 30
>>> import time
>>> endtime = time.time() + timeout
>>> while not stdout.channel.eof_received:
...     sleep(1)
...     if time.time() > endtime:
...         stdout.channel.close()
...         break
>>> stdout.read()
'Starting XXX: \n[  OK  ]\rProgram started . . .\n'
>>>

通常我收到True并且可以只是stdout.read(),但为了安全起见我使用此解决方法(有效!): 等待超时,强制stdout.channel.close()然后stdout.read():

Python 2.6.6
paramiko (1.15.2)

BTW我用:

const std::string input{"word word word word 5 word word 7 word word word word word 8 word word word word. word word word word word word 67. word 9"};

std::regex numbers_pattern(R"((\b\d+()\b))");

for (std::sregex_token_iterator begin(input.begin(), input.end(),
     numbers_pattern, 1), end; begin != end; ++begin)
{
    std::cout << *begin << '\n';
}

希望这会有所帮助......

答案 1 :(得分:1)

我碰巧遇到了这个问题。但是我通过使用“ readline”而不是“ readlines”来解决它。

例如:

client = paramiko.SSHClient()
client.connect(addr, port, username, password)
stdin, stdout, stderr = client.exec_command(cmd)

while True:
    print(stdout.readline())
    if stdout.channel.exit_status_ready():
        break

因此它将立即打印每行并且不再挂起,而且exit_status_ready()可以确保在stdout停止/退出时循环中断。

答案 2 :(得分:0)

如果您在命令完成后期望得到特定的输出,您可以删除 data = stdout.read() 并写入

        while True:
            if "Ended" in str(stdout.readline()):
                stdout.channel.close()
                break

在我的情况下,我的命令将返回“已结束”的内容,因此我会检查它,如果是,则执行 stdout.channel.close() 这解决了我的问题。在您的情况下,“结束”可以是您期望获得的任何内容

答案 3 :(得分:0)

在使用 stdout 之前尝试关闭 stdin。

环境:
python3.8
paramiko-2.7.2

stdin, stdout, stderr = client.exec_command(cmd)
stdin.close()
for line in iter(stout.readline,""):
    print(line, end='')

答案 4 :(得分:-1)

对于仍在为此苦苦挣扎的人:在尝试读取client.close()stdout之前,我可以通过运行stderr来解决此问题。