管道STDERR与STDOUT


24

根据“ Linux:完全参考第六版 ”(第44页),您只能使用|&重定向符号通过管道传输STDERR 。

我已经编写了一个非常简单的脚本来对此进行测试:

#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2

我这样运行此脚本:

./script.sh |& sed 's:^:\t:'

大概只有缩进STDERR的行会缩进。但是,正如我所看到的,它实际上并不像这样工作:

    Normal Text.
    Error Text. 

我在这里做错了什么?

Answers:


26

我不知道您的书使用什么文本,但是bash手册很清楚(如果您已经对重定向有所了解):

如果|&使用,则command1的标准错误,除了其标准输出外,还通过管道连接到command2的标准输入。它是的简写2>&1 |。将标准错误隐式重定向到标准输出是在命令指定的任何重定向之后执行的。

因此,如果您不想混合标准输出和标准错误,则必须将标准输出重定向到其他位置。请参阅如何grep标准错误流(stderr)?

{ ./script.sh 2>&1 >&3 | sed 's:^:\t:'; } 3>&1

双方的fd 1和3 script.sh以及sed但是将指向原来的标准输出目的地。如果您想成为一个好公民,则可以关闭那些命令不需要的fd 3:

{ ./script.sh 2>&1 >&3 3>&- | sed 's:^:\t:' 3>&-; } 3>&1

bashksh93可以将其压缩>&3 3>&->&3-(fd move)。


bash手册对我来说还不是很清楚。我不太明白为什么smth like ./script.sh > /tmp/stdout_goes_here |& grep 'grepping_script_stderr'无法按预期运行,即:redirect script.shstdout(根据手动代码片段应首先发生),然后允许grep处理脚本的stderr。相反,stderr并且tdout`都以stdout_goes_here
sxc731

1
@ sxc731 |&是的简写2>&1 |。因此,>/tmp/stdout_goes_here |&将stdout重定向到/tmp/stdout_goes_here,然后2>&1将stderr重定向到stdout所要去的任何地方,也就是/tmp/stdout_goes_here|由于命令的输出已被重定向,最终没有收到任何输入。请记住,>&1重定向到文件描述符1当前所处的位置,而不是文件描述符1最终所处的位置。仅通过管道传递stderr并将stdout重定向到文件,一种方法是2>&1 >/tmp/stdout_goes_here |
吉尔斯(Gilles)“所以,别再邪恶了”

6

|&将stderr传递到stdin,例如2>&1 |,因此下一个程序将同时在stdin上获得它们。

$cat test.sh
#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2
$./test.sh | sed 's:^:\t:'
Error Text.
        Normal Text.
$ ./test.sh |& sed 's:^:\t:'
        Normal Text.
        Error Text.

哦,所以它基本上等效于更长的表达式runcommand 2>&1 | tee?即runcommand |& tee
2011年

是的,他们是一样的。
凯文

1

|&bash中的只是b的快捷方式(不是非常便于移植)2>&1 |,因此您应该看到每行缩进。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.