【发布时间】:2017-01-18 16:09:36
【问题描述】:
我正在尝试实现一个 ssh 代理,除其他外,该代理将允许我以后以阻塞模式执行命令,在该模式下,一旦可用,就会从通道中读取输出。
这是我到目前为止所拥有的:
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 会话后面没有实际的终端。
所以,我尝试用get_pty = True 调用paramiko 的exec_command():
stdin, stdout, stderr = self.ssh_agent.exec_command(command, get_pty = True)
但后来我发现我失去了在频道上将数据发送到 stderr 的能力(由于某种原因,所有内容都发送到 stdout,即 channel.recv_stderr_ready() 永远不会是 True)。事实上,我在文档中发现了以下内容:
recv_stderr_ready()
如果数据已缓冲并准备好从此通道的 stderr 流中读取,则返回 true。 仅使用 exec_command 或 没有 pty 的 invoke_shell 将永远在 stderr 流上有数据。
返回:如果此通道上的 recv_stderr 调用将立即返回至少一个字节,则为真;否则为假。
我怎样才能两者兼得?
换句话说,我怎样才能摆脱这个:
tput: No value for $TERM and no -T specified
同时还能将stderr 定向到我选择的任何地方?
编辑:
我只是有一个想法...
我可以在远程 shell 中以某种方式定义这个 TERM 变量以消除该错误吗?这是一种常见的方法,还是只是隐藏问题的糟糕解决方法?
【问题讨论】:
标签: python ssh paramiko stderr io-redirection