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

问题描述:

我可以做这样的事情在bash:如何将STDOUT和STDERR记录到单个文件中并使用Ruby在控制台中仅显示STDERR?

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. 如有必要,创建日志文件夹。

我在看Ruby的popen和spawn选项,但我没有看到将STDERR流拆分为两个目标的方法。

此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}" 

您可以使用Open3模块(manual)它返回3个对象:标准输入,标准输出,标准错误

但是,你是不是能够保持输出和错误之间的顺序。

例子:

#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 

使用Ruby尝试this article有关实现类似的功能tee 。你应该可以用它作为你的shell代码的纯红宝石(或至少不含exec)实现的起点。