如何只为一个进程选择性地将stdout保存在文件中?

时间:2015-02-12 14:21:18

标签: python python-2.7 python-3.x

要在txt文件中捕获SSH命令执行会话的输出,我这样做了:

sys.stdout = open('Output_Log.txt','w')

现在,一旦SSH会话关闭,我想停止写入文件并让其他打印语句进入控制台。

但事实并非如此。后续打印正在覆盖我的上述日志文件,而我正在丢失我的SSH命令执行数据。

以下是完整的代码:

  session.exec_command('cd /project/neptune/neptune_psv/fw; ./Do_Regr.sh -i Testlist_Regression.in -m 135.24.237.198 -g')

  stdout_data = []
  stderr_data = []
  sys.stdout = open('Output_Log.txt','w')
  sys.stderr = open('Error_Log.txt','w')

  while True:

   try:
     if session.recv_ready():
      stdout_data.append(session.recv(16384))

     if session.recv_stderr_ready():
      stderr_data.append(session.recv_stderr(16384))

     if session.exit_status_ready():
      break

   except socket.timeout:
    print("SSH channel timeout exceeded.")
    break
   except Exception:
    traceback.print_exc()
   break

  print 'exit status: ', session.recv_exit_status()
  print ''.join(stdout_data)
  print ''.join(stderr_data)

  session.close()
  trans.close()
  print "############Regression Complete############"

当我打开Output_Log.txt时,我只找到最后一个打印件。然而,如果我评论最后一个打印语句(回归完成),那么Output_Log会很好地捕获会话的stdout_data。

3 个答案:

答案 0 :(得分:0)

不是重定向sys.stdoutsys.stderr,而是直接写入文件。您已经在列表中捕获输出 - 使用它有利于您:

try:
    # capture output streams
finally:
    with open('Output_Log.txt', 'w') as output:
        output.write(''.join(stdout_data))
        output.write('\nexit status: %s' % session.recv_exit_status())
    with open('Error_Log.txt', 'w') as output:
        output.write(''.join(stderr_data))

答案 1 :(得分:0)

要在文件中保存ssh命令的输出,请不要重定向Python的stdout / stderr,而是使用subprocess模块:

from subprocess import call

cmd = ['ssh', 'host', 'cd /project/neptune/neptune_psv/fw; '
       './Do_Regr.sh -i Testlist_Regression.in -m 135.24.237.198 -g']
with open('Output_Log.txt', 'w') as out, open('Error_Log.txt','w') as err:
    rc = call(cmd, stdout=out, stderr=err)

或者如果您想继续使用paramiko;对代码的最小更改是使用out.write而不是stdout_data.appenderr.write而不是stderr_data.append其中outerr是对应的文件对象。不要重定向sys.stdoutsys.stderr - 这里没有必要。

为避免丢失数据,即使子流程已完成,也应读取可能缓冲的数据,即在if session.exit_status_ready()之后读取直至EOF(直到空结果)。

答案 2 :(得分:0)

好吧,使用现有代码我找到了一个解决方案:

  stdout_data = []
  stderr_data = []
  temp = sys.stdout      --------- Added this
  sys.stdout = open('Output_Log.txt','w')
  sys.stderr = open('Error_Log.txt','w')

  ---------------Main Code---------------------

  print 'exit status: ', session.recv_exit_status()
  print ''.join(stdout_data)
  print ''.join(stderr_data)

  session.close()
  trans.close()
  sys.stdout.close()
  sys.stdout = temp      ------ Added this

  print "############Regression Complete############"

这对我有用。但我会尝试上面提出的解决方案并稍后回复。