Search code examples
bashhttp-redirectstderr

Echo to stderr and output stderr to a file


I am trying to echo outputs to stderr and redirect stderr to a file at the same time, I noticed that the order of redirection matters, but I don't understand why it has to be this way.

The file asap is empty using either of the following commands:

echo "Fatal error." >&2 2>asap
echo >&2 "Fatal error." 2>asap

But this works, logging "Fatal error" to the file asap.

echo "Fatal error." 2>asap >&2

Why?


Solution

  • See How to pipe stderr and not stdout for most of the required information. Note the 'au contraire' comment, in particular. Remember that all redirections are completed before the command is executed, and that the redirections are processed from left to right. (Pipelines marginally complicate the story. Most of the time, the pipe redirection of standard output is done before any other redirection. The exception is a Bash-specific syntax, |&. Go read the Bash manual for the details — and then don't use |&.)

    Note that the redirections can be positioned anywhere on the command line relative to the command name and arguments. That is:

    <html> xml some -command
    

    is the same as

    some -command <html >xml
    

    and so on. So, there is no difference between the first two commands in the question. (And I think you found that out for yourself.)

    The first command in the question:

    echo "Fatal error." >&2 2>asap
    

    first redirects standard output to the current standard error, then redirects standard error to the file (leaving standard output pointing to the original standard error), and then executes the echo command. The message goes to the original standard error (your terminal), and not to the file because echo doesn't write to standard error.

    The last command:

    echo "Fatal error." 2>asap >&2
    

    first sends standard error to the file, then sends standard output to the same place that standard error is going to (the file), and then executes the echo command. Since standard output is going to the file, there's nothing seen on the terminal.