2016-09-10 6 views
1

sshエージェントを実装しようとしていますが、とりわけ、ブロッキングモードでコマンドを実行できるようになりました。利用できます。ここ
は、私がこれまで持っているものです。Python paramiko:stderrのリダイレクトはget_pty = Trueの影響を受けます

from paramiko import client 

class SSH_Agent: 

    def __init__(self, server_name, username = getpass.getuser(), password = None, connection_timeout = CONNECTION_TIMEOUT): 
     self.ssh_agent = client.SSHClient() 
     self.ssh_agent.set_missing_host_key_policy(client.AutoAddPolicy()) 
     self.ssh_agent.connect(server_name, username = username, password = password if password is not None else username, timeout = connection_timeout) 


    def execute_command(self, command, out_streams = [sys.stdout], err_streams = [sys.stderr], poll_intervals = POLL_INTERVALS): 
     stdin, stdout, stderr = self.ssh_agent.exec_command(command) 
     channel = stdout.channel 
     stdin.close() 
     channel.shutdown_write() 

     while not channel.closed or channel.recv_ready() or channel.recv_stderr_ready(): 
      got_data = False 
      output_channels = select.select([channel], [], [], poll_intervals)[0] 

      if output_channels: 
       channel = output_channels[0] 
       if channel.recv_ready(): 
        for stream in out_streams: 
         stream.write(channel.recv(len(channel.in_buffer))) 
         stream.flush() 
        got_data = True 

       if channel.recv_stderr_ready(): 
        for stream in err_streams: 
         stream.write(channel.recv_stderr(len(channel.in_stderr_buffer))) 
         stream.flush() 
        got_data = True 

      if not got_data \ 
      and channel.exit_status_ready() \ 
      and not channel.recv_ready() \ 
      and not channel.recv_stderr_ready(): 
       channel.shutdown_read() 
       channel.close() 
       break 

     return channel.recv_exit_status() 

(この実装は、私がどこかにここにSOで見つかったものに基づいています)
私はそれをテストするとき、それはコマンドを実行するとき、私はこれを取得することを除いて、正常に動作します:

tput: No value for $TERM and no -T specified 

私はオンラインビットを読み、sshセッションの背後には、実際の端末がありませんので、それが起こるが分かりました。
だから、私は、呼び出そうとしましたparamikoexec_command()get_pty = Trueと:

stdin, stdout, stderr = self.ssh_agent.exec_command(command, get_pty = True) 

しかし、その後、私は、私はすべてが何らかの理由でstdoutに行く(チャネル上stderrにデータを取得する機能を失ってることが判明すなわち、channel.recv_stderr_ready()は決してTrueです)。確かに、私は、docで、次のが見つかりました:

recv_stderr_ready()

をデータをバッファリングし、このチャネルの標準エラー出力ストリームから読み込み可能な場合にtrueを返します。 ptyなしのexec_commandまたは invoke_shellを使用するチャネルだけが、stderrストリームにデータを持ちます。
戻り値:このチャネルのrecv_stderr呼び出しが直ちに少なくとも1バイトを返す場合はtrue。そうでなければFalse。

どうすればいいですか?言い換えれば
は、どのように私はこれを取り除くことができます:

tput: No value for $TERM and no -T specified 

はまだ私が選択した任意の場所にstderrを指示する能力を持ちながら?

EDIT
私はちょうど考えていた...
私は何とかそのエラーを取り除くために、リモートシェルでこのTERM変数を定義することはできますか?これは一般的なアプローチですか、問題を隠すだけの悪い回避策ですか?

答えて

2

* nixシステムで実行していると仮定すると、ptyを作成するのではなく、コマンド環境でTERMを設定することができます。例えば

def execute_command(self, command, out_streams = [sys.stdout], err_streams = [sys.stderr], poll_intervals = POLL_INTERVALS): 
    # Pre-pend required environment here 
    command = "TERM=xterm " + command 
    stdin, stdout, stderr = self.ssh_agent.exec_command(command) 
    channel = stdout.channel 
    stdin.close() 
    channel.shutdown_write() 
    ... 

これはまだ、あなたの既存のコードを使用して別々のストリームへのアクセスを許可する必要があります。

+0

それがトリックでした。 –

関連する問題