将stdout和stderr都重定向到文件,仅打印stdout

时间:2018-09-05 11:30:09

标签: bash maven io-redirection

我在stdoutstderr中输入了大量文本;我想将所有日志记录到一个文件中(以相同顺序),并仅在控制台中打印来自stdout的内容以进行进一步处理(例如grep)。

> file&> file的任何组合,即使与||&一起使用,也将永久重定向流,而我之后将无法对其进行管道传输:

my_command > output.log | grep something  # logs only stdout, prints only stderr
my_command &> output.log | grep something  # logs everything in correct order, prints nothing
my_command > output.log |& grep something  # logs everything in correct order, prints nothing
my_command &> output.log |& grep something  # logs everything in correct order, prints nothing

任何使用tee都会

  • 打印来自stderr的内容然后记录来自stdout的所有内容并打印出来,所以我失去了输入的文本的顺序
  • 如果我使用|& tee,请以正确的顺序记录两者,但是由于现在所有内容都在stdout中,因此我失去了对流的控制。

示例:

my_command | tee output.log | grep something  # logs only stdout, prints all of stderr then all of stdout
my_command |& tee output.log | grep something  # logs everything, prints everything to stdout
my_command | tee output.log 3>&1 1>&2 2>&3 | tee -a output.log | grep something  # logs only stdout, prints all of stderr then all of stdout

现在我全都没主意了。

这是我的测试用例:

testFunction() { 
  echo "output"; 
  1>&2 echo "error"; 
  echo "output-2"; 
  1>&2 echo "error-2"; 
  echo "output-3"; 
  1>&2 echo "error-3";
}

我希望控制台输出如下:

output
output-2
output-3

我的output.log文件如下所示:

output
error
output-2
error-2
output-3
error-3

有关更多详细信息,我用mvn clean install过滤了grep的输出以仅在终端中保留最少的信息,但是我也想在某个地方有完整的日志,以备需要时使用。调查堆栈跟踪或其他内容。 Java测试日志已发送到stderr,因此我选择将其丢弃到控制台输出中。

1 个答案:

答案 0 :(得分:2)

虽然实际上不是使用重定向或任何顺序的解决方案,但您可能要为此使用annotate-output

假设script.sh包含您的函数,则可以执行以下操作:

$ annotate-output ./script.sh                                                     
13:17:15 I: Started ./script.sh
13:17:15 O: output
13:17:15 E: error
13:17:15 E: error-2
13:17:15 O: output-2
13:17:15 E: error-3
13:17:15 O: output-3
13:17:15 I: Finished with exitcode 0

因此,现在可以轻松地重新处理该信息并将其发送到所需的文件:

$ annotate-output ./script.sh \
  | awk '{s=substr($0,13)}/ [OE]: /{print s> "logfile"}/ O: /{print s}'
output
output-2
output-3
$ cat logfile 
output
error
error-2
output-2
error-3
output-3

tee sed cut ...的任何其他组合...

根据@CharlesDuffy的评论:

  

由于stdout和stderr是并行处理的,因此可能会发生          stdout将出现在以后打印的stderr行之前(反之亦然)。

     

不幸的是,使用当前的注释策略很难解决。解决办法          涉及切换到PTRACE'ing过程。给予(比)更高的优先级          但是,执行的程序可能导致这种现象的出现频率降低。

     

来源:man annotate-output