如何管道 stderr,而不是 stdout?

我有一个向stdoutstderr写入信息的程序,我需要在不考虑stdout 的情况下通过grep来了解stderr 的内容

我当然可以分两步完成:

command > /dev/null 2> temp.file
grep 'something' temp.file

但我希望能够在没有临时文件的情况下执行此操作。有任何智能管道技巧吗?

答案

command 2>&1 >/dev/null | grep 'something'
command 3>&1 1>&2 2>&3
command > >(stdlog pipe)  2> >(stderr pipe)
command 2> >(grep 'something') >/dev/null

如果您这样做,请结合以下最佳答案:

command 2> >(grep -v something 1>&2)

... 然后所有 stdout 都保留为 stdout 所有 stderr 都保留为 stderr,但是您不会在 stderr 中看到任何包含字符串 “something” 的行。

这具有不反转或丢弃 stdout 和 stderr,不将它们混在一起或使用任何临时文件的独特优势。

command 2>&1 >/dev/null | grep 'something'
command >/dev/null 2>&1 | grep 'something'
command >/dev/null |& grep "something"
# save tty-stdout to fd 3
exec 3>&1
# switch stdout and stderr, grep (-v) stderr for nasty messages and append to files
exec 2> >(grep -v "nasty_msg" >> std.err) >> std.out
# goes to the std.out
echo "my first message" >&1
# goes to the std.err
echo "a error message" >&2
# goes nowhere
echo "this nasty_msg won't appear anywhere" >&2
# goes to the tty
echo "a message on the terminal" >&3
exec 3>&1
command1 2>&1 >&3 3>&- | command2 3>&-
exec 3>&-
mkfifo stdout-target
mkfifo stderr-target
cat < stdout-target | command-for-stdout &
cat < stderr-target | command-for-stderr &
main-command 1>stdout-target 2>stderr-target

您可以使用rc shell

首先安装该软件包(小于 1MB)。

这个示例说明了如何在rc中将stdout和管道stderr丢弃到 grep:

find /proc/ >[1] /dev/null |[2] grep task

您无需离开 Bash 就可以做到:

rc -c 'find /proc/ >[1] /dev/null |[2] grep task'

您可能已经注意到,可以在管道后面使用方括号来指定要管道传输的文件描述符。

标准文件描述符的编号方式如下:

  • 0:标准输入
  • 1:标准输出
  • 2:标准误差