为了测试目的,我想要将stdout和stderr分别保存下来以便后续代码检查。例如,使用错误输入运行测试应该会导致stderr输出,但是stdout没有任何输出;而使用正确输入运行测试应该会导致stdout输出,但是不会有stderr输出。保存必须是同步的,以避免与测试发生竞争条件(因此无法使用进程替换)。
为了能够事后调试测试,我还需要按它们输出的顺序看到stdout和stderr。所以,我要么将它们都保存到同一个文件/变量/其他地方,要么在同时将它们保存分开时也要将它们发送到终端。
为了测试哪个错误发生了,我还需要命令的退出码。
出于效率和准确性的原因,我当然不能两次运行每个测试。
例如,是否可以将stdout重定向到stdout.log,stderr重定向到stderr.log,并且将它们同时保存到output.log中?还是分别为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
这似乎是有效的,除了最后一次迭代,bar
的值被设置为 stderr 的内容。有没有建议让所有这些都能正常工作?
sed
管道传递,以在行开头添加标记?然后,我们就能够从日志文件中知道哪一行来自哪个流。 - Raphaeltee
,例如:exec > >(sed 's/^/from STDOUT: /' | tee -a mylog) 2> >(sed 's/^/from STDERR: /' | tee -a mylog >&2)
(未经测试)。顺便说一下,这会导致终端输出也具有这些前缀。 - Dennis Williamson