如何将STDERRredirect到STDOUT,但忽略原始STDOUT?
我有一个STDERR
输出的程序,我想检查和运行grep
等。
所以我可以redirect到STDOUT
并使用grep,但问题是,我不想要原始的STDOUT
内容。
所以,这一个不会做
cmd 2>&1 | grep pattern
因为它会混合原始的STDOUT和STDERR。
而这一个不起作用,因为grep不读取STDERR输出:
cmd 1>/dev/null | grep pattern
但是,这个也不行:
cmd 1>/dev/null 2>&1 | grep pattern
因为输出将是完全空的,因为所有东西都写到/dev/null
。
但是一定要有一个简单的方法来做到这一点?
什么不行:
你引用的最后一条命令的原因是:
cmd 1>/dev/null 2>&1 | grep pattern
不起作用,源于redirect的工作顺序的混乱。 您预计最后一次引用redirect将应用于每个输出之前的redirect,以便输出原始标准输出文件描述符(1)将转到/ dev / null,并输出到标准错误文件描述符(2)将去原来的标准输出。
但是,这不是shellredirect的工作方式。 每个redirect通过closures“源”并将“目的地”复制到其中(参见dup(2)
和close(2)
的man
页dup(2)
,使得文件描述符被“重新映射”。 这意味着在你的命令中,标准输出首先被replace为/dev/null
,然后将标准错误replace为标准输出,这已经是/dev/null
了。
什么工作:
因此,要获得所需的效果,只需要反转redirect。 然后你将有标准错误转到标准输出,原始标准输出转到/dev/null
:
cmd 2>&1 >/dev/null | grep pattern
(注意1
之前>
是不必要的 – 对于输出redirect标准输出是默认的)
附录 :Charlie提到redirect到&-
closures文件描述符。 如果使用支持该扩展的交互式shell( bash
和其他一些实现,但不是全部,并且不是标准的 ),你也可以这样做:
cmd 2>&1 >&- | grep pattern
这可能会更好 – 它可以节省一些时间,因为当命令尝试写入标准输出时, write
调用可能会立即失败,而不等待上下文切换到内核,并且驱动程序处理/dev/null
(取决于系统调用实现 – 有些可能会在libc
函数中捕获这个函数,有些可能还会为/dev/null
特殊处理)。 如果有很多输出是值得的,input的速度会更快。
这大部分工作,因为大多数程序不关心,如果他们不写入标准输出(真正检查printf
的返回值?),不会介意标准输出是封闭的。 但是如果write
失败的话,一些程序可以用失败代码来救援 – 通常会阻塞处理器,使用一些小心的I / O库或logging到标准输出的程序。 所以,如果它不工作,请记住,这是一个可能的原因,并尝试/dev/null
。
先closuresSTDOUT:
1>&-, >&-
看到这里 。
我会尝试一些简单的:
cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file