How can I pipe stderr, and not stdout?

后端 未结 11 1184
-上瘾入骨i
-上瘾入骨i 2020-11-22 03:28

I have a program that writes information to stdout and stderr, and I need to process the stderr with grep, leaving

相关标签:
11条回答
  • 2020-11-22 03:55

    First redirect stderr to stdout — the pipe; then redirect stdout to /dev/null (without changing where stderr is going):

    command 2>&1 >/dev/null | grep 'something'
    

    For the details of I/O redirection in all its variety, see the chapter on Redirections in the Bash reference manual.

    Note that the sequence of I/O redirections is interpreted left-to-right, but pipes are set up before the I/O redirections are interpreted. File descriptors such as 1 and 2 are references to open file descriptions. The operation 2>&1 makes file descriptor 2 aka stderr refer to the same open file description as file descriptor 1 aka stdout is currently referring to (see dup2() and open()). The operation >/dev/null then changes file descriptor 1 so that it refers to an open file description for /dev/null, but that doesn't change the fact that file descriptor 2 refers to the open file description which file descriptor 1 was originally pointing to — namely, the pipe.

    0 讨论(0)
  • 2020-11-22 03:56

    If you are using Bash, then use:

    command >/dev/null |& grep "something"
    

    http://www.gnu.org/software/bash/manual/bashref.html#Pipelines

    0 讨论(0)
  • 2020-11-22 04:05

    I just came up with a solution for sending stdout to one command and stderr to another, using named pipes.

    Here goes.

    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
    

    It's probably a good idea to remove the named pipes afterward.

    0 讨论(0)
  • 2020-11-22 04:12

    Combining the best of these answers, if you do:

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

    ...then all stdout is preserved as stdout and all stderr is preserved as stderr, but you won't see any lines in stderr containing the string "something".

    This has the unique advantage of not reversing or discarding stdout and stderr, nor smushing them together, nor using any temporary files.

    0 讨论(0)
  • 2020-11-22 04:14

    In Bash, you can also redirect to a subshell using process substitution:

    command > >(stdlog pipe)  2> >(stderr pipe)
    

    For the case at hand:

    command 2> >(grep 'something') >/dev/null
    
    0 讨论(0)
  • 2020-11-22 04:14

    For those who want to redirect stdout and stderr permanently to files, grep on stderr, but keep the stdout to write messages to a tty:

    # 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
    
    0 讨论(0)
提交回复
热议问题