How do programs output to elsewhere than STDOUT/STDERR? How to avoid it?

The syntax you used is wrong.

cmd &2>1 >file

will be split down as

cmd &
2>1 >file

This will:

  1. Run cmd as a background job with no redirections
  2. In a separate process (without a command!) will redirect stderr to a file literally called 1 and redirect stdout to file

The syntax you want is:

cmd >file 2>&1

The order of operations is important. This will:

  1. Redirect stdout to file
  2. Redirect stderr to &1 - ie the same filehandle as stdout

The result is that both stderr and stdout will be redirected to file.

In bash, a simpler non-standard (and so I don't recommend it, on portability grounds) syntax of cmd &> file does the same thing.


There are two problems.

The first one is that the order matters, the second one is /dev/tty.

Let's use this script as an example script that we want to capture output from:

test.sh:

#!/bin/bash

echo dada
echo edada 1>&2
echo ttdada >/dev/tty

Now let's see the outputs of the commands:

./testmyscript.sh 2>&1 >/dev/null:

edada
ttdada

Because the order of evaluation is from left to right, we first get "redirect stderr to wherever stdout is outputting(so, console output)". Then we get "redirect stdout to /dev/null. We end up with situation like this:

stdout -> /dev/null stderr -> console

So we get it right:

./testmyscript.sh >/dev/null 2>&1

And we get:

ttdada.

Now we do "Redirect stdout to /dev/null", and then "Redirect stderr to where stdout is pointing"(so, /dev/null). Hurray!

However, we still have a problem; program prints to /dev/tty. Now I don't know how to fix this kind of behaviour, so you're most likely going to need script, but hopefully this behaviour won't happen too often.