Bash 如何将STDERR重定向到STDOUT,而忽略原始STDOUT?
我有一个程序,它的Bash 如何将STDERR重定向到STDOUT,而忽略原始STDOUT?,bash,redirect,stdout,Bash,Redirect,Stdout,我有一个程序,它的STDERR输出我想检查并运行grep等 因此,我可以将其重定向到STDOUT并使用grep,但问题是,我不想要原始STDOUT内容 所以,这个不行 cmd 2>&1 | grep pattern 因为它将混合原始标准输出和标准输出 因为grep不读取STDERR的输出,所以这个不起作用: cmd 1>/dev/null | grep pattern 但是,这一个也不起作用: cmd 1>/dev/null 2>&1 | grep p
STDERR
输出我想检查并运行grep
等
因此,我可以将其重定向到STDOUT
并使用grep,但问题是,我不想要原始STDOUT
内容
所以,这个不行
cmd 2>&1 | grep pattern
因为它将混合原始标准输出和标准输出
因为grep不读取STDERR的输出,所以这个不起作用:
cmd 1>/dev/null | grep pattern
但是,这一个也不起作用:
cmd 1>/dev/null 2>&1 | grep pattern
因为输出将完全为空,因为所有内容都写入/dev/null
但是必须有一个简单的方法来完成它?首先关闭STDOUT:
1>&-, >&-
请看。我会尝试一些简单的方法,比如:
cmd 2> tmp_file && cat tmp_file | grep pattern && rm -f tmp_file
什么不起作用:
您引用上一条命令的原因:
cmd 1>/dev/null 2>&1 | grep pattern
不起作用,源于对重定向工作顺序的混淆。您希望最后引用的重定向应用于每个输出上它之前的重定向,以便原始标准输出文件描述符(1)的输出将转到/dev/null,而标准错误文件描述符(2)的输出将转到原始标准输出
但是,shell重定向不是这样工作的。每次重定向都会通过关闭“源”并将“目标”复制到其中(请参见dup(2)
和close(2)
的man
页面),从而“重新映射”文件描述符。这意味着在命令中,标准输出首先被替换为/dev/null
,然后标准错误被替换为标准输出,标准输出已经是/dev/null
工作原理:
因此,要获得所需的效果,只需反转重定向即可。然后将标准错误转到标准输出,原始标准输出转到/dev/null
:
cmd 2>&1 >/dev/null | grep pattern
(请注意,>
之前的1
是不必要的-对于输出重定向,标准输出是默认值)
附录:Charlie提到重定向到
&-
关闭文件描述符。如果使用支持该扩展的交互式shell(bash
和其他一些实现,但不是全部,而是全部),您也可以这样做:
cmd 2>&1 >&- | grep pattern
这可能更好—它可以节省一些时间,因为当命令尝试写入标准输出时,write
调用可能会立即失败,而无需等待上下文切换到内核和驱动程序处理/dev/null
(取决于系统调用实现-有些可能在libc
函数中捕捉到这一点,有些可能还具有对/dev/null
的特殊处理)。如果有大量值得输入的输出,则可以更快地输入
这将主要起作用,因为大多数程序都不关心是否无法写入标准输出(谁真正检查
printf
?)的返回值)并且不会介意标准输出被关闭。但是,如果写入
失败,一些程序可能会带着故障代码退出—通常会阻塞处理器,程序使用一些小心的库进行I/O或记录到标准输出。因此,如果它不起作用,请记住这是一个可能的原因,并尝试/dev/null
Uhmm,您确定吗这就可以满足OP的要求了?对我来说似乎不行。如果你先关闭stdout,就没有办法将stderr重定向到它。好的,基于此,我发现这是有效的:2>&1>&-。也许你可以更新答案,因为在当前编写的时候,你可能会尝试以下方法:>&-2>&1,这是无效的。是的,那样(在重定向后关闭它)它可以工作,而且在受支持的情况下,有时比使用/dev/null更好,因为您可以在写操作时进行保存—我将更新我的答案以说明这一点,但在sh中显然不是标准的。关闭stdout,而不是发送到/dev/null,只有当写入stdout的命令忽略了写入时的错误时才起作用——这是对C编程的一个悲哀的评论,事实上,大多数时候,程序会忽略这些错误。@Charlie Martin。对,它被标记为bash,答案可能是好的。我不这么认为对bash的扩展了解得太多了,所以我在这里学到了一些新东西:-)选择的答案表明这是不必要的。你在第二部分中使用cat是无缘无故的。由于存在诊断输出,因此命令很有可能返回错误状态,&&将不会有帮助。我建议删除这一点。也考虑输出可能非常大,而CAT只会在最后看到GRIP,如果没有足够的空间写入临时文件,则会花费更多的时间,并且失败。除非您以后需要随机访问输出,否则最好使用“动态”管道。很棒的工作!毫无疑问,每当我需要它的时候,我都会一遍又一遍地回到这个页面来查找它。