shell 如何让STDOUT和STDERR都转到终端和日志文件-并保留stdout/stderr?

2nc8po8w  于 2022-12-13  发布在  Shell
关注(0)|答案(1)|浏览(201)

这是这个问题的后续问题:
How do I get both STDOUT and STDERR to go to the terminal and a log file?
简而言之:我想运行一个命令,并将STDOUT * 和 * STDERR存储在 * 一个 * 日志文件中(以保持时间相关性),但我仍然需要在STDERR上打印STDERR输出。
动机:有一些工具运行一个命令,并以不同的方式处理STDOUTSTDERR-例如,以不同的颜色打印STDERR,或者当命令返回非零值时打印STDERR
因此,我希望有一种方法可以将所有输出存储在一个日志文件中,同时保留STDOUTSTDERR之间的区别(以及返回代码)。

log-output --file=command.log -c "make stuff-with-stderr"

从我发现在上述链接的答案至少有两种不同的方法:

the_cmd 1> >(tee stdout.txt ) 2> >(tee stderr.txt >&2 )

会将STDOUTSTDERR储存在不同的档案中,因此会失去时间相关性。不幸的是,STDOUTSTDERR都只会打印在STDOUT上。

script -e -B build.log -c "the_cmd"

STDOUTSTDERR存储在 * 一个 * 文件中,保持时间相关性,但仍仅在STDOUT上打印STDOUTSTDERR
所以这些方法都不符合我的要求。还有别的吗?

jpfvwuh4

jpfvwuh41#

编辑:

在bash shell中使用我的方法和下面注解中的命令(pip3 install -U pytest),您可以得到想要的结果:

(((pip3 install -U pytest | tee -a log.txt) 3>&1 1>&2 2>&3 | tee -a log.txt) 3>&1 1>&2 2>&3)

log.txt中的条目总是按照正确的顺序(与在终端中执行pip3 install -U pytest相同),并且输出被正确地打印到终端(stdout和stderr的单独流)。我怀疑存在更好的解决方案,但这似乎是解决该问题的“可行”解决方案。

原始答案:

可能还有一个比这个更简单的解决方案,但是你可以把stdout转换成log.txt,然后把stdout和stderr交换,把“新的”stdout(stderr)转换成log.txt,然后把stderr和stdout交换回来,然后把两个流都输出到终端(类似于here的例子):

((({ echo "test_out"; echo "test_err" 1>&2; } | tee -a log.txt) 3>&1 1>&2 2>&3 | tee -a log.txt) 3>&1 1>&2 2>&3)
test_out
test_err

cat log.txt
test_out
test_err

# show stdout/stderr are still separate streams:
((({ echo "test_out"; echo "test_err" 1>&2; } | tee -a log.txt) 3>&1 1>&2 2>&3 | tee -a log.txt) 3>&1 1>&2 2>&3) 1>std.out 2>std.err

cat std.out
test_out

cat std.err
test_err

相关问题