【问题标题】:redirect stdout and stderr to one file, copy of just stderr to another将 stdout 和 stderr 重定向到一个文件,将 stderr 复制到另一个文件
【发布时间】:2015-09-12 06:23:53
【问题描述】:

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

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

但也将 stderr 重定向到单独的文件。我尝试了以下变体:

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

但它们都不能在 bash 中正常工作,例如stderr 仅被重定向到输出文件之一。重要的是,合并后的文件保留第一个代码 sn-p 的行顺序,因此不会转储到单独的文件并稍后合并。

在 bash 中有一个巧妙的解决方案吗?

【问题讨论】:

  • 我认为您无法通过单个进程来做到这一点,当然也不能像问题所示那样简单地扭曲重定向。您可能可以通过管道将某些内容发送到tee,但由于缓冲等原因,结果的交错可能与您在终端屏幕上看到的不同。
  • 请注意,您的第一个命令 (./foo.sh 2>&1 >file) 将错误发送到原始标准输出,并将标准输出(但不是重定向的标准错误)发送到文件。如果你想同时使用file,你必须使用./foo.sh >file 2>&1,颠倒重定向的顺序。它们被解释为从左到右阅读。
  • 说得对,刚刚修复了 2>&1 的顺序,谢谢@JonathanLeffler

标签: bash


【解决方案1】:

您可以使用额外的文件描述符和tee

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

请注意,行缓冲可能会导致 stdout 输出出现乱序。如果这是一个问题,有一些方法可以解决这个问题,包括使用unbuffer

【讨论】:

  • 这看起来像一个简单的单行,但不能让它工作。我得到“bash:意外标记'}'附近的语法错误”。删除分号消除了错误,但是当我尝试对文件进行分类时,我得到 'bash: 3: Bad file descriptor'
  • @CyGuy:如果你不包括左大括号或省略它后面的空格,你会得到那个错误。
  • 尊重空间时确实有效@DennisWilliamson
  • @DennisWilliamson,当它们不是 完全相同的文件描述符的副本时,我看不出 POSIX 语义如何允许 unbuffer 或任何其他工具来确定 stderr 和 stdout 之间的写入顺序我>。如果您涉及 FIFO,则写入 FIFO 和另一端的程序计划从中读取之间所涉及的延迟量(然后,在 tee 的情况下,使用它读取的内容)是不确定的,无论链前面的刷新有多立即。
【解决方案2】:

使用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 打开的,这样每次写入都会在最后完成,而不管其他进程也写入了什么。

如 cmets 中所述,通常情况下,输出的交错方式与您在终端运行 ./foo.sh 时的方式不同。有多组缓冲正在进行,以确保发生这种情况。由于线条突破缓冲区大小边界的方式,您也可能会得到部分线条。

【讨论】:

    【解决方案3】:

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

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

    如果您希望两者都在文件中,则必须使用./foo.sh >file 2>&1,颠倒重定向的顺序。

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

    【讨论】:

    • 我对问题中重定向的评论是有效的,但不能解决问题。问题是如何让一个 write 函数调用同时写入两个不同的文件,简短的回答是“你不能”。所以,标准错误必须写在可以复制两份的地方。
    猜你喜欢
    • 1970-01-01
    • 2014-07-22
    • 2013-02-15
    • 2023-01-10
    • 1970-01-01
    • 2011-12-28
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多