将stdout和stderr重定向到文件,仅打印标准输出[复制]

问题描述 投票:3回答:1

我有大量的文字来自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所以我选择在我的控制台输出中丢弃它。

bash maven io-redirection
1个回答
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的过程。然而,给予执行程序更好的(更高)优先级可能会导致此行为不那么频繁地出现。

来源:man annotate-output

© www.soinside.com 2019 - 2024. All rights reserved.