考虑这个 Bash 函数:
func() {
( echo STDOUT; echo STDERR >&2 ) 1>$1 2>$2
}
然后是这个:
$ func /dev/stdout /dev/stdout | wc -l
2
$ func /dev/stdout /dev/stderr | wc -l
STDERR
1
这些是预期的。
然后这个:
$ func /dev/stderr /dev/stdout | wc -l
STDOUT
STDERR
0
我会期待
STDOUT
1
这里:
STDOUT
写入stderr(wc
看不到),STDERR
写入stdout(wc
看到)。
另一张:
$ func /dev/null /dev/stdout | wc -l
0
我希望
STDERR
被写入标准输出,因此可以被 wc
看到。
这里发生了什么事?
如何实现我想要的?
执行重定向后
1>/dev/stderr
,stdout
相当于stderr
。然后,当它执行时,2>/dev/stdout
,/dev/stdout
表示原始的stderr,因此它将stderr重定向到已经要去的地方。两个 FD 都写到同一个地方。
如果要交换 stdout 和 stderr,则需要在重定向之前将原始流之一保存在某处。
some_cmd 3>&1 1>&2 2>&3 3>&-
这会将 stdout 保存在 fd 3 上,将 stderr 复制到 stdout,将 fd 3 (原始 stdout)复制到 stderr,然后关闭临时 fd 3。