15

Apparently I don't know all the output destinations that are available for use. I know about stdout(&1) and stderr (&2). However, after redirecting both descriptors, I sometimes still get some output in my console!

The easiest example I can think of is GNU Parallel; Each time I use it, I see a citation notice. Even when I do &2>1 > file, I still see the notice.

And the same applies to emerge: When I run emerge and there are some problems, some informations aren't printed to stdout nor stdin, since I redirect them and they still get through.

I mostly solve these problems by using script, but I am still wondering what's causing this issue.

  • 1
    Please provide a full example. – Kusalananda Jul 15 '16 at 11:13
  • which shell? have a look at mywiki.wooledge.org/BashFAQ/055 and stackoverflow.com/questions/876239/… – Sundeep Jul 15 '16 at 11:22
  • 8
    You won't get them all. A script can always write to /dev/tty. – Satō Katsura Jul 15 '16 at 11:26
  • 1
    As for GNU parallel: mkdir ~/.parallel; touch ~/.parallel/will-cite will disable the annoying message. Alternatively, look around for other implementations of parallel. – Satō Katsura Jul 15 '16 at 11:30
  • 2
    @OleTange Because it isn't a problem - I'm asking why something is happening and I'm using parallel as an example. – MatthewRock Jul 15 '16 at 13:55
40

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.

  • Nice, thanks. The other problem might be /dev/tty, but hopefully this doesn't happen too often(if at all). – MatthewRock Jul 15 '16 at 11:43
  • 5
    If you have the at command on your machine and have privileges to use it, then you can run the command via at now. See the manpage for details. This will run the command via a batch process mechanism and the process will never have a tty to write to. But, in general, I wouldn't worry about this edge case. Typically only processes requiring interaction and deliberately need to display things to users despite redirection will use /dev/tty. – Stephen Harris Jul 15 '16 at 11:48
  • been there, done that – davidbak Jul 15 '16 at 17:59
10

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.