保存标准输出,标准错误和标准输出+标准错误同步 [英] Save stdout, stderr and stdout+stderr synchronously

查看:154
本文介绍了保存标准输出,标准错误和标准输出+标准错误同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关测试的目的,我想保存输出和错误的分别的供后续code检查。例如,错误输入测试运行会导致输出到标准错误,但没有在标准输出上,同时用正确的输入测试运行会导致输出到标准输出,但没有到stderr。保存有是同步的,以避免与测试(所以我不能使用过程中的竞争条件替代)。

要能够在事后调试测试,我的需要看到输出和错误,他们输出的顺序排列。所以,我不得不要么他们两个保存到同一文件/变量/不管或发送到终端在同一时间分别节省了他们。

要测试它的错误发生了,我的所需要的命令的退出code。

有关效率和准确性的原因,我当然不能运行两次,每次测试。

难道例如可以重定向标准输出到stdout.log,错误输出到stderr.log,的两个人在同一个命令output.log?或者使用的同步 T恤命令分别对输出和错误?或者输出和错误的副本保存到不同的变量?

更新:它看起来像Tim的解决方案几乎作品(修改输出端子,而不是记录到all.log):

  $设置-o pipefail
$ {
    {
        回声富|三通stdout.log 2 - ;和3 3 GT;&放大器; -
    } 2 - ;&放大器1为卤素;和4 4为H.&放大器; - |三通stderr.log 2 - ;和3 3 GT;&放大器; -
} 3 GT;和2 4 GT;&放大器; 1

$猫stdout.log

$猫stderr.log
$ {
    {
        回声富>和2 |三通stdout.log 2 - ;和3 3 GT;&放大器; -
    } 2 - ;&放大器1为卤素;和4 4为H.&放大器; - |三通stderr.log 2 - ;和3 3 GT;&放大器; -
} 3 GT;和2 4 GT;&放大器; 1

$猫stdout.log
$猫stderr.log

$栏= $({
    {
        回声富|三通stdout.log 2 - ;和3 3 GT;&放大器; -
    } 2 - ;&放大器1为卤素;和4 4为H.&放大器; - |三通stderr.log 2 - ;和3 3 GT;&放大器; -
} 3>和2 4为H.&放大器; 1)
$回声$栏

$猫stdout.log

$猫stderr.log
$栏= $({
    {
        回声富>和2 |三通stdout.log 2 - ;和3 3 GT;&放大器; -
    } 2 - ;&放大器1为卤素;和4 4为H.&放大器; - |三通stderr.log 2 - ;和3 3 GT;&放大器; -
} 3>和2 4为H.&放大器; 1)
$猫stdout.log
$猫stderr.log

$回声$栏

这似乎除了最后一次迭代,其中条的值设置为标准错误的内容合作。所有这些有什么建议工作?


解决方案

请参见 BashFAQ / 106 。这是不容易有你鱼与熊掌兼得了。

在这个页面:


  

但是有些人不会接受输出和错误,或线条的不同步之间的分离或者损失。他们是纯粹主义者,因此他们要求所有的最困难的形式 - 我想请结合stdout和stderr到一个文件中,但我也希望他们能够保持原来的,独立的目的


  
  

在为了做到这一点,我们首先要提出几点注意事项:


  
  

      
  • 如果有将是两个独立的输出和错误流,那么一些过程有写他们每个人。

  •   
  • 有没有办法写在shell脚本,由两个独立的文件描述符读取每当其中一人有输入可用过程中,由于外壳没有调查(2)或选择(2)接口。

  •   
  • 因此,我们需要两个独立的作家的过程。

  •   
  • 要保持两个独立作家毁坏对方输出的唯一方法是,以确保他们无论是在追加方式打开它们的输出。即中追加模式打开一个FD都有,每一次数据写入的保障属性,则跳到结束第一。

  •   

  
  

所以:


 #猛砸
> mylog
EXEC> >(三通-a mylog)2 - ; >(三通-a mylog>和2)回声A>和2
猫文件
回声B>和2


  

这确保日志文件是正确的。它并不能保证作家的下一个shell提示符之前完成:


 〜$ ./foo
一个
喜的妈妈

〜$猫mylog
一个
喜的妈妈

〜$ ./foo
一个
喜的妈妈
〜$ B

此外,请参阅 BashFAQ / 002 并的 BashFAQ / 047

For testing purposes, I would like to save stdout and stderr separately for inspection by subsequent code. For example, a test run with erroneous input should result in output to stderr, but nothing on stdout, while a test run with correct input should result in output to stdout, but nothing to stderr. The saving has to be synchronous, to avoid race conditions with the tests (so I can't use process substitution).

To be able to debug the test after the fact, I also need to see stdout and stderr in the sequence they were output. So I have to either save them both to the same file/variable/whatever or send them to the terminal at the same time as saving them separately.

To test which error happened, I also need the exit code of the command.

For reasons of efficiency and accuracy, I of course cannot run each test twice.

Is it for example possible to redirect stdout to stdout.log, stderr to stderr.log, and both of them to output.log in the same command? Or to use a synchronous tee command separately for stdout and stderr? Or to save a copy of stdout and stderr to separate variables?

Update: It looks like tim's solution almost works (modified to output on terminal instead of logging to all.log):

$ set -o pipefail
$ {
    {
        echo foo | tee stdout.log 2>&3 3>&-
    } 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1
foo
$ cat stdout.log
foo
$ cat stderr.log
$ {
    {
        echo foo >&2 | tee stdout.log 2>&3 3>&-
    } 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1
foo
$ cat stdout.log
$ cat stderr.log
foo
$ bar=$({
    {
        echo foo | tee stdout.log 2>&3 3>&-
    } 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1)
$ echo "$bar"
foo
$ cat stdout.log
foo
$ cat stderr.log
$ bar=$({
    {
        echo foo >&2 | tee stdout.log 2>&3 3>&-
    } 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1)
$ cat stdout.log
$ cat stderr.log
foo
$ echo "$bar"
foo

This seems to work except for the last iteration, where the value of bar is set to the contents of stderr. Any suggestions for all of these to work?

解决方案

Please see BashFAQ/106. It's not easy to have your cake and eat it, too.

From that page:

But some people won't accept either the loss of separation between stdout and stderr, or the desynchronization of lines. They are purists, and so they ask for the most difficult form of all -- I want to log stdout and stderr together into a single file, BUT I also want them to maintain their original, separate destinations.

In order to do this, we first have to make a few notes:

  • If there are going to be two separate stdout and stderr streams, then some process has to write each of them.
  • There is no way to write a process in shell script that reads from two separate FDs whenever one of them has input available, because the shell has no poll(2) or select(2) interface.
  • Therefore, we'll need two separate writer processes.
  • The only way to keep output from two separate writers from destroying each other is to make sure they both open their output in append mode. A FD that is opened in append mode has the guaranteed property that every time data is written to it, it will jump to the end first.

So:

# Bash
> mylog
exec > >(tee -a mylog) 2> >(tee -a mylog >&2)

echo A >&2
cat file
echo B >&2

This ensures that the log file is correct. It does not guarantee that the writers finish before the next shell prompt:

~$ ./foo
A
hi mom
B
~$ cat mylog
A
hi mom
B
~$ ./foo
A
hi mom
~$ B

Also, see BashFAQ/002 and BashFAQ/047.

这篇关于保存标准输出,标准错误和标准输出+标准错误同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆