so.*_*red 5 python ssh paramiko stderr io-redirection
我正在尝试实现一个 ssh 代理,除其他外,它允许我稍后在阻塞模式下执行命令,在该模式下,只要输出可用,就会从通道中读取输出。
\n这是我到目前为止所拥有的:
from paramiko import client\n\nclass SSH_Agent:\n\n def __init__(self, server_name, username = getpass.getuser(), password = None, connection_timeout = CONNECTION_TIMEOUT):\n self.ssh_agent = client.SSHClient()\n self.ssh_agent.set_missing_host_key_policy(client.AutoAddPolicy())\n self.ssh_agent.connect(server_name, username = username, password = password if password is not None else username, timeout = connection_timeout)\n\n\n def execute_command(self, command, out_streams = [sys.stdout], err_streams = [sys.stderr], poll_intervals = POLL_INTERVALS):\n stdin, stdout, stderr = self.ssh_agent.exec_command(command)\n channel = stdout.channel\n stdin.close()\n channel.shutdown_write()\n\n while not channel.closed or channel.recv_ready() or channel.recv_stderr_ready():\n got_data = False\n output_channels = select.select([channel], [], [], poll_intervals)[0]\n\n if output_channels:\n channel = output_channels[0]\n if channel.recv_ready():\n for stream in out_streams:\n stream.write(channel.recv(len(channel.in_buffer)))\n stream.flush()\n got_data = True\n\n if channel.recv_stderr_ready():\n for stream in err_streams:\n stream.write(channel.recv_stderr(len(channel.in_stderr_buffer)))\n stream.flush()\n got_data = True\n\n if not got_data \\\n and channel.exit_status_ready() \\\n and not channel.recv_ready() \\\n and not channel.recv_stderr_ready():\n channel.shutdown_read()\n channel.close()\n break\n\n return channel.recv_exit_status()\nRun Code Online (Sandbox Code Playgroud)\n\n(这个实现基于我在 SO 中找到的一个)
\n当我测试它时,它工作正常,除了我在执行命令时得到这个:
tput: No value for $TERM and no -T specified\nRun Code Online (Sandbox Code Playgroud)\n\n我在网上读了一些内容,发现发生这种情况是因为会话后面没有实际的终端ssh。
\n所以,我尝试用paramiko以下方式exec_command()调用get_pty = True:
stdin, stdout, stderr = self.ssh_agent.exec_command(command, get_pty = True)\nRun Code Online (Sandbox Code Playgroud)\n\nstderr但后来我发现我失去了在通道上获取数据的能力(一切都出于stdout某种原因,即channel.recv_stderr_ready()永远不会True)。事实上,我在文档中发现了以下内容:
\n\n\nrecv_stderr_ready()
\n\n如果数据已缓冲并准备好从此通道\xe2\x80\x99s stderr 流读取,则返回 true。只有使用 exec_command 或不带 pty 的 invoke_shell 的通道才会在 stderr 流上有数据。
\n
\n 返回:如果此通道上的 recv_stderr 调用将立即返回至少一个字节,则返回 True;否则为假。
我怎样才能两者兼得?
\n换句话说,我怎样才能摆脱这个:
tput: No value for $TERM and no -T specified\nRun Code Online (Sandbox Code Playgroud)\n\n同时仍然能够定向stderr到我选择的任何地方?
编辑:
\n我只是有一个想法...
\n我可以以某种方式TERM在远程 shell 中定义这个变量来消除该错误吗?这是一种常见的方法还是一种只会隐藏问题的糟糕解决方法?
假设您在 *nix 系统上运行,您可以尝试TERM在命令环境中进行设置,而不是创建 pty。
例如:
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()
...
Run Code Online (Sandbox Code Playgroud)
这仍然允许您使用现有代码访问单独的流。
| 归档时间: |
|
| 查看次数: |
5157 次 |
| 最近记录: |