Problem: stderr redirection is not working.
Before we start, let’s define a simple function that writes data to stderr instead of stdout.
|
1 |
$ echostderr () { echo "$@" 1>&2; } |
What the echostderr function will do is to print whatever arguments that are passed to it to stderr.
|
1 2 |
$ echostderr "printing to stderr" printing to stderr |
Now, let’s say that we want to redirect stderr and stdout output to a file, how should we do it? Well, we redirect stderr to stdout and then redirect stdout to a file? Well, let’ see.
|
1 2 3 4 |
$ echostderr "printing to stderr" 2>&1 > out.log printing to stderr $ cat out.log $ |
Well, it looks like the stderr output was never redirected to the out.log file. Instead, it was sent to the terminal.
What went wrong? Well, the reason is simple. For multiple redirections, the order is important. They’re evaluated from left to right. If you want to redirect stderr or both stderr and stdout to the same file, this is the wrong way to do it.
Let’s look at why it is not working.
- Initially, both
stderrandstdoutpoint to the terminal. - Then
2>&1redirectsstderrtostdout, which points to the terminal. So effectively,stderris not redirected at all. Or, it was redirected from the terminal back to the terminal again. - Lastly,
> out.logwill redirectstdoutfrom the terminal toout.logfile. Whilestdoutgot redirected to out.log,stderris still pointing to the terminal.
To make it work, we have to swap the order of redirection.
|
1 2 3 |
$ echostderr "printing to stderr" > out.log 2>&1 $ cat out.log printing to stderr |
So, what happens now is:
- Both
stderrandstdoutpoint to the terminal initially. stdoutis redirected to “out.log” file.stderris redirected tostdout, which is currently pointing to the “out.log” file.

