我想知道是否可以将标准输入分叉到 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.out
,test.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
。