将stdout和stderr重定向到一个文件,将stderr的副本重定向到另一个文件

时间:2015-09-11 21:59:17

标签: bash

我想将stdout和stderr的输出重定向到一个公共文件:

./foo.sh >stdout_and_stderr.txt 2>&1

但是也只是将stderr重定向到一个单独的文件。我尝试了各种变体:

./foo.sh >stdout_and_stderr.txt 2>stderr.txt 2>&1

但是他们都没有在bash中正常工作,例如stderr只被重定向到其中一个输出文件。组合文件保留第一个代码片段的行顺序非常重要,因此不要转储到单独的文件中,以后再合并。

在bash中是否有一个简洁的解决方案?

3 个答案:

答案 0 :(得分:3)

您可以使用其他文件描述符和tee

{ foo.sh 2>&1 1>&3- | tee stderr.txt; } > stdout_and_stderr.txt 3>&1

请注意,行缓冲可能会导致stdout输出无序显示。如果这是一个问题,有办法克服这个问题,包括使用unbuffer

答案 1 :(得分:1)

使用process substitution,您可以获得适度的近似值:

file1=stdout.stderr
file2=stderr.only
: > $file1    # Zap the file before starting
./foo.sh >> $file1 2> >(tee $file2 >> $file1)

这会命名文件,因为其中一个名称会重复出现。标准输出写入$file1。将标准错误写入管道,该管道运行tee并将输入的一个副本(标准错误输出)写入$file2,并将第二个副本写入$file1>>重定向意味着文件以O_APPEND打开,因此每次写入都将在最后完成,无论其他进程也写了什么。

正如评论中所指出的,一般来说,输出的交错方式与您在终端上只运行./foo.sh时的输出方式不同。有多组缓冲正在进行以确保发生的事情。您可能还会获得部分线,因为线条会突破缓冲区大小边界。

答案 2 :(得分:0)

来自@ jonathan-leffler的评论应该是一个答案:

请注意,您的第一个命令(./foo.sh 2>&1 >file)会将错误发送到原始标准输出,并将标准输出(但不是重定向的标准错误)发送到文件。

如果你想要两个文件,你必须使用./foo.sh >file 2>&1,颠倒重定向的顺序。

他们被解释为从左到右阅读。