paramiko 合并 stdout 和 stderr
我正在尝试把标准输出和标准错误的结果合并在一起。我认为可以通过一个叫做set_combine_stderr()的Channel对象来实现。
这是我正在做的事情:
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()),我遇到了以下错误:
错误:通道已关闭。
任何帮助都将非常感谢。
3 个回答
@AaronMcSmooth: 我指的是我通过SSH连接的电脑上的标准输出和错误输出。
我最后做了这个:
stdin, stdout, stderr = ssh.exec_command(...)
output = stdin.read().strip() + stdout.read().strip()
对于我的应用来说,区分标准输出和错误输出并不重要,但我觉得把它们合在一起的方式不是最好的。
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
我在这个通道上执行相同的操作,但收到了“通道已关闭”的错误。
好的,我知道这个话题有点老了,但我遇到了同样的问题,找到了一种(可能不太)好看的解决办法。你只需要在远程服务器上运行命令,把错误信息(stderr)重定向到标准输出(stdout),然后始终从标准输出读取信息。比如:
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()
虽然说 set_combine_stderr
可以把 stderr
(错误信息)转到 stdout
(正常输出)流里,但它的顺序是乱七八糟的,所以你得到的结果可能不是你想要的。你可能希望看到的,是按写入顺序排列的行,就像在本地终端窗口运行命令一样。相反,应该使用 get_pty
。这样做会让服务器通过一个伪终端来运行这些行,保持它们的时间顺序。
这里有一个测试程序,叫 outerr.py
,它会在 stdout
和 stdin
上交替写入行。假设它位于 llmps@meerkat2 的主目录下。
#!/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
的行会随机混在一起。