12

我正在尝试结合标准输出和标准错误的输出。我的信念是,这可以通过 Channel 对象的 set_combine_stderr() 来完成。

这就是我正在做的事情:

SSH = paramiko.SSHClient()
#I connect and everything OK, then:
chan = ssh.invoke_shell()
chan.set_combine_stderr(True)
chan.exec_command('python2.6 subir.py')
resultado = chan.makefile('rb', -1.)

但是,当我尝试存储结果时出现以下错误(上面的最后一行, chan.makefile() ):

错误:通道关闭。

任何帮助将不胜感激

4

3 回答 3

18

虽然确实会set_combine_stderr转移stderrstdout流中,但它是以混乱的顺序进行的,因此您不会得到您可能想要的结果,即按写入顺序组合的行,就像您在本地终端窗口中运行命令一样. 相反,使用get_pty. 这将导致服务器通过伪终端运行这些行,使它们按时间顺序排列。

这是一个测试程序 ,它在和outerr.py上交替写入行。假设它位于 llmps@meerkat2 的主目录中。stdoutstdin

#!/usr/bin/env python

import sys

for x in xrange(1, 101):
    (sys.stdout, sys.stderr)[x%2].write('This is line #%s, on std%s.\n' %
                (x, ('out', 'err')[x%2]))

现在尝试以下代码远程运行它:

#!/usr/bin/env python

import paramiko

def connect():
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect('meerkat2', username='llmps', password='..')
    return ssh

def runTest(ssh):
    tran = ssh.get_transport()
    chan = tran.open_session()
    # chan.set_combine_stderr(True)
    chan.get_pty()
    f = chan.makefile()
    chan.exec_command('./outerr.py')
    print f.read(),

if __name__ == '__main__':
    ssh = connect()
    runTest(ssh)
    ssh.close()

如果你运行上面的代码,你应该会看到 100 行的写法。相反,如果您注释掉该chan.get_pty()调用并取消注释该调用,您将得到从运行到运行随机散布chan.set_combine_stderr(True)的团块stdout和行。stderr

于 2011-11-08T03:53:13.523 回答
5

好的,我知道这是一个相当古老的话题,但我遇到了同样的问题,我得到了一个(也许不是那么)漂亮的解决方案。只需在远程服务器上调用命令,将标准错误重定向到标准输出,然后始终从标准输出读取。例如:

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('hostname', username='user', password='pass')

stdin,stdout,stderr = client.exec_command('python your_script.py 2> \&1')
print stdout.read()
于 2016-09-23T15:01:27.457 回答
3

@AaronMcSmooth:我指的是我正在连接的计算机的标准输出和标准错误(通过 SSH)。

我最终这样做了:

stdin, stdout, stderr = ssh.exec_command(...)

output = stdin.read().strip() + stdout.read().strip()

对于我的应用程序而言,区分 stdout 和 stderr 并不重要,但我认为这不是将两者结合起来的最佳方式。

的代码SSHClient.exec_command()是(查看paramiko的源代码):

def exec_command(self, command, bufsize=-1):
    chan = self._transport.open_session() 
    chan.exec_command(command) 
    stdin = chan.makefile('wb', bufsize) 
    stdout = chan.makefile('rb', bufsize) 
    stderr = chan.makefile_stderr('rb', bufsize) 
    return stdin, stdout, stderr

我正在频道上执行相同的操作,但收到频道已关闭错误。

于 2010-09-30T00:31:51.023 回答