将 stdin 分叉到 stdout 和 stderr?

将 stdin 分叉到 stdout 和 stderr?

我想知道是否可以将标准输入分叉到 stdout 和 stderr?像这样的事情,

$ echo "hi" | fork > std.out 2> std.err
$ cat std.out
hi
$ cat std.err
hi

或者,我是否缺少一些可以让我将输入分叉到两个不同目标的东西?该tee命令看起来很接近我想要的,但我不想写入文件。谢谢。

答案1

我需要理解 Linux 中经典的“一切都是文件”。该tee实用程序将标准输入复制到标准输出,并将副本复制到文件。因此,识别 stderr 写入的文件,/dev/stderr允许将 stdin 写入两个文件并重新定向,如下所示 -

$ echo "hi" | tee /dev/stderr > test.out 2> test.err
$ cat test.out
hi
$ cat test.err
hi

答案2

在 zsh 中,当您多次重定向 fd 进行输出时,zsh 会在内部进行分叉,因此您可以这样做:

echo hi >&1 >&2

输出到 stdout 和 stderr。

不过,如果您想将其输出到 和test.outtest.err您可以这样做:

echo hi > test.out > test.err

反而。

在基于 Linux 和 Cygwin 之外的系统上,您可以使用以下命令执行相同操作

echo hi | tee /dev/stderr

在 Linux 和 Cygwin 上,这是错误的,除非 stderr 碰巧在管道或 tty 上打开,因为打开/dev/stderr会重新打开 stderr (fd 2) 指向的文件,因此,例如,如果 stderr 被重定向到日志文件,那么它将替换包含该行的日志文件hi,如果 stderr 打开到套接字,则会失败,因为套接字不能打开

-a选项添加到tee(对于附加模式)可以帮助处理日志文件的情况。

使用具有进程替换支持的 shell 的另一种解决方法是使用:

echo hi | tee >(cat >&2)

但这也有其自身的问题,例如在某些 shell 中,例如bash,不等待该cat命令,因此您可以看到此类问题:

$ bash -c 'echo hi | tee >(cat >&2); echo after >&2'
hi
after
hi

echo after运行在哪里,之前cat有时间写过hi

相关内容