如何将STDERR重定向到STDOUT,但忽略原始STDOUT? [重复]

时间:2022-03-14 00:02:33

This question already has an answer here:

这个问题在这里已有答案:

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 not want 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?

但必须有一个简单的方法来做到这一点?

3 个解决方案

#1


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重定向的工作原理。每个重定向都会通过关闭“源”并将“目标”复制到其中来“重新映射”文件描述符(请参阅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>是不必要的 - 对于输出重定向标准输出是默认的)


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:

附录:Charlie提到重定向到& - 关闭文件描述符。如果使用支持该扩展的交互式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.

这可能会更好 - 它可以节省一些时间,因为当命令尝试写入标准输出时,写入的调用可能会立即失败,而无需等待上下文切换到内核和驱动程序处理/ 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的返回值?)并且不介意标准输出被关闭。但是如果写入失败,某些程序可以使用失败代码进行挽救 - 通常会阻塞处理器,程序使用一些仔细的I / O库或记录到标准输出。因此,如果它不起作用,请记住这是一个可能的原因并尝试/ dev / null。

#2


Close STDOUT first:

首先关闭STDOUT:

1>&-, >&-

See here.

#3


I would try something simple like:

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

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

#1


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重定向的工作原理。每个重定向都会通过关闭“源”并将“目标”复制到其中来“重新映射”文件描述符(请参阅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>是不必要的 - 对于输出重定向标准输出是默认的)


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:

附录:Charlie提到重定向到& - 关闭文件描述符。如果使用支持该扩展的交互式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.

这可能会更好 - 它可以节省一些时间,因为当命令尝试写入标准输出时,写入的调用可能会立即失败,而无需等待上下文切换到内核和驱动程序处理/ 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的返回值?)并且不介意标准输出被关闭。但是如果写入失败,某些程序可以使用失败代码进行挽救 - 通常会阻塞处理器,程序使用一些仔细的I / O库或记录到标准输出。因此,如果它不起作用,请记住这是一个可能的原因并尝试/ dev / null。

#2


Close STDOUT first:

首先关闭STDOUT:

1>&-, >&-

See here.

#3


I would try something simple like:

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

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