如何将STDOUT和STDERR记录到单个文件中并使用Ruby在控制台中仅显示STDERR?

时间:2011-03-01 18:59:48

标签: ruby redirect

我可以在bash中做这样的事情:

myCommand arg1 arg2 2>&1 >> myLogFolder/myLogFile.log | tee -a myLogFolder/myLogFile.log

我希望能够这样说:

log.rb myLogFolder/myLogFile.log myCommand arg1 arg2

使用log.rb脚本可以完成两件事:

  1. 结果是一个更简单的语句,重定向技巧更少,只有一个日志文件规范。
  2. 如有必要,请创建日志文件夹。
  3. 我正在查看Ruby的popen和spawn选项,但我没有看到将STDERR流拆分为两个目的地的方法。

3 个答案:

答案 0 :(得分:0)

您可以使用Open3模块(manual)它返回3个对象:stdin,stdout,stderr

但是,您无法保留stdout和stderr之间的顺序。

示例:

#include <stdio.h>

int main(int argc, char *argv[]) {
  fprintf(stdout, "Normal output\n");
  fprintf(stderr, "Error output\n");
  fprintf(stdout, "Normal output\n");
}

它被捕获为:

Normal output
Normal output
Error output

如何保留订单的唯一方法是运行程序两次。 : - (

示例ruby代码:

#!/usr/bin/env ruby

require 'open3'
require 'pathname'

logfile = ARGV.first()
cmd = ARGV.drop(1).join(" ")

dir = Pathname(logfile).dirname

if not File.directory?(dir)
    Dir.mkdir(dir)
end 

file = File.open(logfile, "w")
stdin, stdout, stderr = Open3.popen3(cmd)
stdin.close()

file.puts(stdout.read())
error = stderr.read()
file.puts(error)
puts error

file.close

答案 1 :(得分:0)

这个Ruby脚本满足了我的需求,但也许有更好的方法。

logPath = ARGV[0]
logFolder = File.dirname(logPath)
command = ARGV.slice(1..-1).join(" ")
`mkdir -p #{logFolder}`
exec "#{command} 2>&1 >> #{logPath} | tee -a #{logPath}"

答案 2 :(得分:0)

尝试this article使用Ruby实现类似于tee的功能。您应该能够将其用作shell代码的纯ruby(或至少exec - 免费)实现的起点。