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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:57:32  来源:igfitidea点击:

How can I redirect STDERR to STDOUT, but ignore the original STDOUT?

bashredirectstdout

提问by Frank

I have a program whose STDERRoutput I want to inspect and run grepon etc.

我有一个程序,STDERR我想检查并运行其输出grep等。

So I could redirect it to STDOUTand use grep, but the problem is, I do notwant the original STDOUTcontent.

所以我可以将它重定向到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 manpages 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/nullalready.

但是,这不是 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 1before >is unnecessary - for output redirection standard output is the default)

(注意1before>是不必要的 - 对于输出重定向标准输出是默认值)



Addendum: Charlie mentioned redirecting to &-to close a file descriptor. If using an interactive shell which supports that extension (bashand 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 writemay 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 libcfunction, 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 writefails - 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 Charlie Martin

Close STDOUT first:

首先关闭标准输出:

1>&-, >&-

See here.

这里

回答by Martin Cote

I would try something simple like:

我会尝试一些简单的事情,例如:

cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file