出于测试目的,我想保存输出和错误分别通过随后的代码检查.例如,具有错误输入的测试运行应该导致输出到stderr,但是在stdout上没有输出,而具有正确输入的测试运行应该导致输出到stdout,但是没有输出到stderr.保存必须是同步的,以避免测试的竞争条件(因此我不能使用进程替换).
为了能够在事后调试测试,我还需要在输出的序列中看到stdout和stderr.因此,我必须将它们保存到相同的文件/变量/任何/或者同时将它们发送到终端,以便单独保存它们.
为了测试发生了哪个错误,我还需要命令的退出代码.
出于效率和准确性的原因,我当然不能每次测试两次.
例如,可以将stdout重定向到stdout.log,将stderr重定向到stderr.log,并将它们都重定向到output.log中的同一命令吗?或者为stdout和stderr分别使用同步 tee命令?或者将stdout和stderr的副本保存为单独的变量?
更新:看起来tim的解决方案几乎可以工作(修改为在终端上输出而不是记录到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
Run Code Online (Sandbox Code Playgroud)
这似乎有效,除了最后一次迭代,其中值bar设置为stderr的内容.有关所有这些工作的建议吗?
Pau*_*ce. 11
请参阅BashFAQ/106.吃蛋糕并吃它也不容易.
从该页面:
但是有些人不会接受stdout和stderr之间失去分离,或者行的去同步化.他们是纯粹主义者,因此他们要求最困难的形式 - 我想将stdout和stderr一起记录到一个文件中,但我也希望他们保持原来的独立目的地.
为了做到这一点,我们首先要做一些笔记:
- 如果要有两个单独的stdout和stderr流,那么一些进程必须编写它们中的每一个.
- 没有办法在shell脚本中编写一个进程,只要其中一个有可用的输入就从两个独立的FD中读取,因为shell没有poll(2)或select(2)接口.
- 因此,我们需要两个独立的编写器进程.
- 保持两个独立编写器的输出不会相互破坏的唯一方法是确保它们都以追加模式打开它们的输出.在追加模式下打开的FD具有保证的属性,即每次向其写入数据时,它将首先跳到最后.
所以:
# Bash
> mylog
exec > >(tee -a mylog) 2> >(tee -a mylog >&2)
echo A >&2
cat file
echo B >&2
Run Code Online (Sandbox Code Playgroud)
这可确保日志文件正确无误.它不保证编写器在下一个shell提示符之前完成:
~$ ./foo
A
hi mom
B
~$ cat mylog
A
hi mom
B
~$ ./foo
A
hi mom
~$ B
Run Code Online (Sandbox Code Playgroud)
另请参阅BashFAQ/002和BashFAQ/047.
| 归档时间: |
|
| 查看次数: |
4396 次 |
| 最近记录: |