10

リモート Linux マシンでコマンドを実行し、Paramiko を使用して出力を読み取るコードがあります。コード定義は次のようになります。

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(IPAddress, username=user['username'], password=user['password'])


chan = self.ssh.get_transport().open_session()

chan.settimeout(10800)

try:
    # Execute thecommand
    chan.exec_command(cmd)

    contents = StringIO.StringIO()

    data = chan.recv(1024)

    # Capturing data from chan buffer.
    while data:
        contents.write(data)
        data = chan.recv(1024)

except socket.timeout:
    raise socket.timeout


output = contents.getvalue()

return output,chan.recv_stderr(600),chan.recv_exit_status()

上記のコードは出力が小さい場合は機能しますが、出力が大きい場合はスタックします。

ここにバッファ関連の問題はありますか?

4

6 に答える 6

8

Bruce Wayne(:))からの入力で機能する最終的なコードを投稿しています

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(IPAddress, username=user['username'], password=user['password'])

chan = self.ssh.get_transport().open_session()
chan.settimeout(10800)

try:
    # Execute the given command
    chan.exec_command(cmd)

    # To capture Data. Need to read the entire buffer to capture output
    contents = StringIO.StringIO()
    error = StringIO.StringIO()

    while not chan.exit_status_ready():
        if chan.recv_ready():
            data = chan.recv(1024)
            #print "Indside stdout"
            while data:
                contents.write(data)
                data = chan.recv(1024)

        if chan.recv_stderr_ready():            
            error_buff = chan.recv_stderr(1024)
            while error_buff:
                error.write(error_buff)
                error_buff = chan.recv_stderr(1024)

    exit_status = chan.recv_exit_status()

except socket.timeout:
    raise socket.timeout

output = contents.getvalue()
error_value = error.getvalue()

return output, error_value, exit_status
于 2013-02-12T12:55:49.727 に答える
3

stdoutチャネルに関連する問題はありませんが、stderrの処理方法がわかりません。確認できますか、それは問題を引き起こしているものをキャプチャしているstderrではありませんか?私はあなたのコードを試して、あなたに知らせます。

更新:実行するコマンドがSTDERRで多くのメッセージを表示すると、コードがフリーズします。理由はわかりませんが、それrecv_stderr(600)が理由かもしれません。したがって、標準出力をキャプチャするのと同じ方法でエラーストリームをキャプチャします。何かのようなもの、

contents_err = StringIO.StringIO()

data_err = chan.recv_stderr(1024)
while data_err:
    contents_err.write(data_err)
    data_err = chan.recv_stderr(1024)

最初にそれ以上に変更recv_stderr(600)してみることもできます。recv_stderr(1024)

于 2013-02-08T10:14:59.573 に答える
2

実際、上記のすべての回答は実際の問題を解決できないと思います。

リモート プログラムが最初に大量のstderr 出力を生成する場合

stdout.readlines()
stderr.readlines()

永遠にハングアップします。でも

stderr.readlines()
stdout.readlines()

はこのケースを解決しますが、リモート プログラムが最初に大量のstdout 出力を生成すると失敗します。

私はまだ解決策を持っていません...

于 2014-02-13T03:29:42.313 に答える
1

開いている ssh セッションの高レベル表現を使用すると、より簡単になります。すでにssh-clientを使用してチャネルを開いているため、そこからコマンドを実行するだけで、余分な作業を回避できます。

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(IPAddress, username=user['username'], password=user['password'])

stdin, stdout, stderr = ssh.exec_command(cmd)
for line in stdout.readlines():
    print line
for line in stderr.readlines():
    print line

後で追加のデータを受け取った場合は、戻ってこれらのファイル ハンドルから再度読み取る必要があります。

于 2013-02-11T15:18:25.980 に答える
0

paramiko コマンドを subprocess.call のように動作させるには、次のコードを使用できます (python-3.5 および paramiko-2.1.1 でテスト済み):

#!/usr/bin/env /usr/bin/python3                                                

import os                                                                  
import sys                                                                                                                    
from paramiko import SSHClient, AutoAddPolicy               
from socket import getfqdn                                       

class SecureSHell(object):                                                 
    reuser = os.environ['USER']                                            
    remote = ''                                                            
    def __init__(self, *args, **kwargs):                                   
        for arg in args:                                                   
            if hasattr(self, arg):                                         
                setattr(self, arg, True)                                   
        for (key, val) in kwargs.items():                                  
            if hasattr(self, key):                                         
                setattr(self, key, val)

    @staticmethod                                                          
    def _ssh_(remote, reuser, port=22):                                    
        if '@' in remote:                                                  
            _reuser, remote = remote.split('@')                            
        _fqdn = getfqdn(remote)                                            
        remote = _fqdn if _fqdn else remote                                
        ssh = SSHClient()                                                  
        ssh.set_missing_host_key_policy(AutoAddPolicy()) 
        ssh.connect(remote, int(port), username=reuser)                                                                     
        return ssh                                                         

    def call(self, cmd, remote=None, reuser=None):                         
        remote = remote if remote else self.remote                         
        reuser = reuser if reuser else self.reuser              
        ssh = self._ssh_(remote, reuser)                                   
        chn = ssh.get_transport().open_session()                           
        chn.settimeout(10800)                                              
        chn.exec_command(cmd)                                              
        while not chn.exit_status_ready():                                 
            if chn.recv_ready():                                           
                och = chn.recv(1024)                                       
                while och:                                                 
                    sys.stdout.write(och.decode())                         
                    och = chn.recv(1024)                                   
            if chn.recv_stderr_ready():                                    
                ech = chn.recv_stderr(1024)                                
                while ech:                                                 
                    sys.stderr.write(och.decode())                         
                    ech = chn.recv_stderr(1024)                            
        return int(chn.recv_exit_status())                                 

ssh = SecureSHell(remote='example.com', user='d0n')                       
ssh.call('find')                                                           
于 2017-01-15T20:25:34.410 に答える