如何将错误输出重定向到标准输出和标准错误输出?

6
我正在组建一条复杂的管道,想把stderr包含在程序输出中以便记录,但我也希望错误仍然保留在stderr中,以便我能够发现问题。
我找到了这个问题,询问如何将stdout+stderr重定向到文件中,并仍然在终端上获得stderr;它很接近,但我还不想将stdout重定向到文件:程序的输出将被其他脚本使用,因此我希望它保留在stdout(同样适用于stderr)。所以,总结一下:
- 脚本将在fd 1中产生输出,在fd 2中产生错误。 - 我希望调用程序重新排列事物,使得输出+错误显示在fd 1中,错误显示在fd 2中。 - 另外,错误应与输出交错(尽可能地进行自己的缓冲),而不是保存并添加到最后。

尽职调查笔记:通过2>&1可以轻松捕获stderr。通过管道tee,保存和查看stdout也很容易。我还知道如何将stdout重定向到文件,并通过管道引导stderr:command 2>&1 1>fileA | tee fileB。但是我如何复制stderr并把stdout放回fd 1?

1个回答

5

为了生成标准输出和标准错误输出的测试,让我们使用以下命令:

{ echo out; echo err >&2; }

以下代码演示了如何将stdout和stderr都发送到管道中的下一步骤,同时也将stderr发送到终端:
$ { echo out; echo err >&2; } 2> >(tee /dev/stderr) | cat >f
err
$ cat f
out
err

它是如何工作的

  • 2>

    这将stderr重定向到其后面的文件(伪文件)。

  • >(tee /dev/stderr)

    这是进程替换,它充当一个接收stderr输入的伪文件。它接收到的任何输入都会发送到tee命令,该命令将其发送到stderr和stdout。


没错,进程替换!这就是将非标准输出重定向到管道的方法...但是在tee子进程中使用>&1有什么意义呢?看起来它只是将标准输出变成了标准输出的副本。 - alexis
此外,将错误发送到 /dev/tty 可能会起作用,但这不是我所希望的——如果我需要将“标准错误”捕获到文件中,那么我将不得不处理脚本的内部结构。 - alexis
看起来 2> >(tee /dev/stderr) 正好满足了我的需求。谢谢! - alexis
@alexis 好建议!我更新了答案,改为转到/dev/stderr - John1024
1
非常感谢。我之前使用了x=$(some_function | tee /dev/stderr)并通过PIPESTATUS来测试成功与否,但这种方法不起作用。但是通过你的解决方案,它可以正常工作。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接