standard error
我对standard output
……的了解非常有限。
常见的方法之一是重定向standard error
到standard output
.这是否意味着错误(通常会转到)因为重定向standard error
而不会再出现?standard error
如果这是真的,是否有任何方法可以复制standard error
、重定向副本并让原始内容按预期standard output
定向?standard error
答案1
在我接触 Unix 的早期,有人向我解释管道的工作原理就像管道一样。
一个流程基本上有 3 个用于填充的连接点:
stdin
|
+--+--+
| pgm |
++---++
| |
stdout stderr
所以,当你这样做时cat | grep pattern
,你会得到
stdin
|
+--+--+
| cat |
++---++
stdout| |stderr
| \
stdin| \
+------+ |
| grep | |
+-+---++ |
stdout| | |
| \__ |
| \|
| |stderr
(那时候都是ascii图形……)
当您将 stderr 重定向到 stdout 时,如图所示pgm 2>&1
,图片变为:
stdin |
|
+--+--+
| pgm |
++---++
stdout| |stderr
| /
| /
| /
|/
|
理论上,您可以通过这种方式完成很多管道工作。例如:awk '{print;print > "/dev/stderr"}'
将 stdin 复制到 stdout 和 stderr。
然而,它很快就会变得非常混乱。详细信息请参阅 bash 手册。
笔记:pgm = 上图中的程序。
编辑:为了好玩,我尝试使用简单的 shell 脚本进行一些更复杂的管道操作。
generate.sh
:
echoerr() { echo "$@" 1>&2; }
for i in 1 2 3 4 5 6 ; do
echo "STDOUT $i"
echoerr "STDERR $i"
done
和copytee.sh
:
#!/bin/bash
echoerr() { echo "$@" 1>&2; }
while read line; do
echo "stdout $line"
echoerr "stderr $line"
done
(请注意,copytee ads 小写,generate 添加大写)
要获得高级形式的重定向,bash generate.sh 2> >(bash copytee.sh )
请给出输出:
STDOUT 1
STDOUT 2
STDOUT 3
STDOUT 4
STDOUT 5
STDOUT 6
stdout STDERR 1
stderr STDERR 1
stdout STDERR 2
stderr STDERR 2
stdout STDERR 3
stderr STDERR 3
stdout STDERR 4
stderr STDERR 4
stdout STDERR 5
stderr STDERR 5
stdout STDERR 6
stderr STDERR 6
这正是你所要求的。
答案2
“标准误差”并不是一个特别定义的地方。 “标准错误”是附加到文件描述符 2 的任何内容。
当您将“标准错误”重定向到“标准输出”时,您所做的是关闭文件描述符 2,然后将其作为文件描述符 1 的副本重新打开,因此它会附加到文件描述符 1 恰好附加到的任何位置那一刻。原来的文件描述符2丢失了(字面意思就是文件描述符被关闭)。所以,你不能完全做你想做的事。如果您将“标准错误”重定向到其他地方,文件描述符 2 将被关闭(并重新打开以将其附加到您重定向到的任何位置),并且不再有任何有关它“应该在”的位置的信息。