bash 如何将 STDERR 重定向到 STDOUT,但忽略原始 STDOUT?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/549737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I redirect STDERR to STDOUT, but ignore the original STDOUT?
提问by Frank
I have a program whose STDERR
output I want to inspect and run grep
on etc.
我有一个程序,STDERR
我想检查并运行其输出grep
等。
So I could redirect it to STDOUT
and use grep, but the problem is, I do notwant the original STDOUT
content.
所以我可以将它重定向到STDOUT
并使用 grep,但问题是,我不想要原始STDOUT
内容。
So, this one won't do
所以,这个不行
cmd 2>&1 | grep pattern
because it will mix the original STDOUT and STDERR.
因为它会混合原始的 STDOUT 和 STDERR。
And this one doesn't work since grep doesn't read the STDERR output:
这一个不起作用,因为 grep 不读取 STDERR 输出:
cmd 1>/dev/null | grep pattern
But also, this one won't work:
但是,这个也行不通:
cmd 1>/dev/null 2>&1 | grep pattern
because the output will be completely empty, since everything gets written to /dev/null
.
因为输出将完全为空,因为所有内容都被写入/dev/null
.
But there must be a simple way to do it?
但必须有一个简单的方法来做到这一点?
回答by Tom Alsberg
What does not work:
什么不起作用:
The reason the last command you quoted:
您引用的最后一条命令的原因:
cmd 1>/dev/null 2>&1 | grep pattern
does not work, stems from a confusion on the order in which redirection works. You expected the last quoted redirection to be applied to the ones before it on every output, so that output the original standard output file descriptor (1) will go to /dev/null, and output to the standard error file descriptor (2) will go to the original standard output.
不起作用,源于对重定向工作顺序的混淆。您期望最后引用的重定向在每次输出时应用于它之前的重定向,以便输出原始标准输出文件描述符 (1) 将转到 /dev/null,并且输出到标准错误文件描述符 (2) 将转到原始标准输出。
However, this is not how shell redirection works. Each redirection causes the file descriptors to be "remapped" by closing the "source" and duplicating the "destination" into it (see the man
pages of dup(2)
and close(2)
), in order. This means that in your command standard output is first replaced with /dev/null
, and then standard error replaced with standard output, which is /dev/null
already.
但是,这不是 shell 重定向的工作方式。每个重定向导致文件描述符被“重新映射”通过关闭“源”和复制“目的地”进去(看man
的网页dup(2)
和close(2)
),为了。这意味着在您的命令中,标准输出首先替换为/dev/null
,然后标准错误替换为标准输出,这/dev/null
已经是。
What works:
什么工作:
Therefore, to obtain the desired effect, you just need to reverse the redirections. Then you will have standard error go to standard output, and the original standard output go to /dev/null
:
因此,要获得所需的效果,您只需要反转重定向即可。然后您将标准错误转到标准输出,原始标准输出转到/dev/null
:
cmd 2>&1 >/dev/null | grep pattern
(note that the 1
before >
is unnecessary - for output redirection standard output is the default)
(注意1
before>
是不必要的 - 对于输出重定向标准输出是默认值)
Addendum: Charlie mentioned redirecting to &-
to close a file descriptor. If using an interactive shell which supports that extension (bash
and some other implementations do but not all and it is not standard), you can also do it like this:
附录:查理提到重定向&-
到关闭文件描述符。如果使用支持该扩展的交互式 shell(bash
和一些其他实现,但不是全部,它不是标准的),你也可以这样做:
cmd 2>&1 >&- | grep pattern
This may be better - it can save some time, because when the command tries to write to standard output the call to write
may fail immediately without waiting for a context switch into the kernel and the driver handling /dev/null
(depending on the system call implementation - some may catch this in the libc
function, and some may also have special handling for /dev/null
). If there is a lot of output that can be worthwhile, and it's faster to type.
这可能更好 - 它可以节省一些时间,因为当命令尝试写入标准输出时,调用write
可能会立即失败,而无需等待上下文切换到内核和驱动程序处理/dev/null
(取决于系统调用实现 - 有些可能在libc
函数中捕获它,有些还可能对/dev/null
)进行特殊处理。如果有很多值得输出的输出,并且输入速度会更快。
This will mostly work because most programs do not care if they fail to write to standard output (who really checks the return value of printf
?) and will not mind that standard output is closed. But some programs can bail out with a failure code if write
fails - usually block processors, programs using some careful library for I/O or logging to stdandard output. So if it doesn't work remember that this is a likely cause and try /dev/null
.
这通常会起作用,因为大多数程序不关心它们是否无法写入标准输出(谁真正检查printf
?的返回值)并且不会介意标准输出已关闭。但是,如果write
失败,某些程序可以通过失败代码退出- 通常会阻塞处理器、使用一些谨慎的 I/O 库或记录到标准输出的程序。因此,如果它不起作用,请记住这是一个可能的原因并尝试/dev/null
。
回答by Martin Cote
I would try something simple like:
我会尝试一些简单的事情,例如:
cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file