首页 文章

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

提问于
浏览
56

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

我有一个程序 STDERR 输出我要检查并运行 grep 等 .

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

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

3 回答

  • 3

    什么行不通:

    你引用的最后一个命令的原因:

    cmd 1>/dev/null 2>&1 | grep pattern
    

    不起作用,源于对重定向工作顺序的混淆 . 您希望最后引用的重定向应用于每个输出之前的重定向,以便输出原始标准输出文件描述符(1)将转到/ dev / null,并输出到标准错误文件描述符(2)将转到原始标准输出 .

    但是,这不是shell重定向的工作原理 . 每个重定向都会导致文件描述符为"remapped",方法是关闭"source"并将"destination"复制到其中(参见 dup(2)close(2)man 页面) . 这意味着在您的命令中,标准输出首先被 /dev/null 替换,然后标准错误替换为标准输出,这已经是 /dev/null .

    什么有效:

    因此,要获得所需的效果,您只需要反转重定向 . 然后你会有标准错误转到标准输出,原始标准输出转到 /dev/null

    cmd 2>&1 >/dev/null | grep pattern
    

    (注意 > 之前的 1 是不必要的 - 输出重定向标准输出是默认的)


    附录:Charlie提到重定向到 &- 以关闭文件描述符 . 如果使用支持该扩展的交互式shell( bash 和其他一些实现但不是全部,并且它是not standard),您也可以这样做:

    cmd 2>&1 >&- | grep pattern
    

    这可能会更好 - 它可以节省一些时间,因为当命令尝试写入标准输出时,对 write 的调用可能会立即失败而不等待上下文切换到内核并且驱动程序处理 /dev/null (取决于系统调用实现 - 有些人可能会在 libc 函数中捕捉到这个,有些人也可能会对 /dev/null 进行特殊处理 . 如果有很多输出是值得的,那么键入的速度会更快 .

    这将主要起作用,因为大多数程序不关心它们是否无法写入标准输出(谁真正检查 printf 的返回值?)并且不介意标准输出被关闭 . 但是如果 write 失败,一些程序可以使用失败代码进行挽救 - 通常会阻止处理器,程序使用一些仔细的I / O库或记录到标准输出 . 因此,如果它不起作用,请记住这是一个可能的原因并尝试 /dev/null .

  • 96

    首先关闭STDOUT:

    1>&-, >&-
    

    here .

  • -4

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

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

相关问题