web-dev-qa-db-ja.com

paramiko pythonモジュールがstdout.read()でハングする

私は以下のコードを使用しています:

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接続とコマンドの実行に適したモジュールはありますか?

11
user3378508

関連する可能性があります https://github.com/paramiko/paramiko/issues/109

以下は、私が直面していることと、それをどのように回避したかについての説明です。

Stdout.channel.eof_received == 0が原因でこの問題も発生しました

import paramiko
client = paramiko.SSHClient()
client.set_missing_Host_key_policy(paramiko.AutoAddPolicy())
client.connect("1.1.1.1", username="root", password="pass")
stdin, stdout, stderr = client.exec_command("service XXX start")

stdin、stdout、およびstderrは開いたままです...

>>> 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))>>>

したがって、EOFは受信されませんでした...

>>> print stdin.channel.eof_received
0

通常、私はTrueを受け取り、stdout.read()だけを使用できますが、安全のために、この回避策を使用します(これは機能します!):タイムアウトを待ち、stdout.channel.close()を強制してからstdout.read():

>>> 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'
>>>

ところで私は使用します:

Python 2.6.6
paramiko (1.15.2)

お役に立てれば...

16
Dmitry Tokarev

私はたまたまこの問題に出くわしました。しかし、私は「readlines」の代わりに「readline」を使用することでそれを回避しています。

例えば:

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
Carl Cheung

これは、stdoutにデータがない場合、またはeolのない行がある場合(つまり、shスクリプト内のreadステートメント内)に発生していました。 'get_pty = True'を設定してから、stdoutのバイトのみを読み取ってみてください。無限ループを回避するには、continueステートメントにもかかわらずタイムアウトとスリープを設定することをお勧めします。

stdin, stdout, stderr = ssh.exec_command("your-command",get_pty=True)
stdout.flush()
nbytes = 0
while (len(stdout.channel.in_buffer)==0):
     continue

nbytes=len(stdout.channel.in_buffer)
print(nbytes)
stdout.read(nbytes)
0
nachopol

まだこれに苦労している人のために:私はstdoutまたはstderrから読み取ろうとする前にclient.close()を実行することでこれを修正することができました。

0
Bryan Bugyi