Unix / Linux: Redirect of stderr Not Working

Problem: stderr redirection is not working.

Before we start, let’s define a simple function that writes data to stderr instead of stdout.

$ echostderr () { echo "$@" 1>&2; }

What the echostderr function will do is to print whatever arguments that are passed to it to stderr.

$ 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.

$ 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 stderr and stdout point to the terminal.
  • Then 2>&1 redirects stderr to stdout, which points to the terminal. So effectively, stderr is not redirected at all. Or, it was redirected from the terminal back to the terminal again.
  • Lastly, > out.log will redirect stdout from the terminal to out.log file. While stdout got redirected to out.log, stderr is still pointing to the terminal.

To make it work, we have to swap the order of redirection.

$ echostderr "printing to stderr" > out.log 2>&1
$ cat out.log
printing to stderr

So, what happens now is:

  • Both stderr and stdout point to the terminal initially.
  • stdout is redirected to “out.log” file.
  • stderr is redirected to stdout, which is currently pointing to the “out.log” file.

ibrahim = { interested_in(unix, linux, android, open_source, reverse_engineering); coding(c, shell, perl, php, python, java, javascript, nodejs, angular, react); plays_on(xbox, ps4); linux_desktop_user(true); }