31

I wanted to know the difference between the following two commands

2>&1 > output.log 

and

2>&1 | tee output.log

I saw one of my colleague use second option to redirect. I know what 2>&1 does, my only question is what is the purpose of using tee where a simple redirection ">" operator can be used?

migrated from stackoverflow.com Sep 10 '11 at 22:33

This question came from our site for professional and enthusiast programmers.

23

Editorial note

Please make sure to read the comments on this answerderobert.


Original answer

2>&1 >output.log means first start sending all file handle 2 stuff (standard error) to file handle 1 (standard output) then send that to the file output.log. In other words, send standard error and standard output to the log file.

2>&1 | tee output.log is the same with the 2>&1 bit, it combines standard output and standard error on to the standard output stream. It then pipes that through the tee program which will send its standard input to its standard output (like cat) and also to the file. So it combines the two streams (error and output), then outputs that to the terminal and the file.

The bottom line is that the first sends stderr/stdout to the file, while the second sends it to both the file and standard output (which is probably the terminal unless you're inside another construct which has redirected standard output).

I mention that last possibility because you can have stuff like:

(echo hello | tee xyzzy.txt) >plugh.txt

where nothing ends up on the terminal.

  • 13
    -1 You have the syntax right, but not the semantics. Run cat /doesnotexist 2>&1 >output.txt - you will see see cat: /doesnotexist: No such file or directory displayed to the terminal and output.txt is an empty file. Order of precedence and closure are in play: 2>&1 (dup fd2 from the current fd1), then >output.txt (redirect fd1 to output.txt, not changing anything else). The reason that 2>&1 | is different is because of order of precedence: | before >. – Arcege Sep 10 '11 at 23:33
  • 5
    This answer is fundamentally wrong in essentially every respect. Many of the answers below are better, but I think this one by Kusalananda is the clearest. – Michael Homer Jan 22 at 2:46
  • 1
    @user14408: Should you ever make an account on Unix & Linux and claim this answer, please feel free to remove my editorial note once you've addressed the comments. – derobert Jan 22 at 19:01
8

First command will do the another task:

After

2>&1 > output.log 

the old STDOUT will be saved (copied) in STDERR and then STDOUT will be redirected to file.

So, stdout will go to file and stderr will go to console.

And in

 2>&1 | tee output.log

both streams will be redirected to tee. Tee will duplicate any input to its stdout (the console in your case) and to file (output.log).

And there is another form of first:

    > output.log  2>&1

this will redirect both STDOUT and STDERR to the file.

8

Looking at the two commands separately:

utility 2>&1 >output.log 

Here, since redirections are processed in a left-to-right manner, the standard error stream would first be redirected to wherever the standard output stream goes (possibly to the console), and then the standard output stream would be redirected to a file. The standard error stream would not be redirected to that file.

The visible effect of this would be that you get what's produced on standard error on the screen and what's produced on standard output in the file.

utility 2>&1 | tee output.log

Here, you redirect standard error to the same place as the standard output stream. This means that both streams will be piped to the tee utility as a single intermingled output stream, and that this standard output data will be saved to the given file by tee. The data would additionally be reproduced by tee in the console (this is what tee does, it duplicates data streams).

Which ever one of these is used depends on what you'd like to achieve.

Note that you would not be able to reproduce the effect of the second pipeline with just > (as in utility >output.log 2>&1, which would save both standard output and error in the file). You would need to use tee to get the data in the console as well as in the output file.


Additional notes:

The visible effect of the first command,

utility 2>&1 >output.log 

would be the same as

utility >output.log

I.e., the standard output goes to the file and standard error goes to the console.

If a further processing step was added to the end of each of the above commands, there would be a big difference though:

utility 2>&1 >output.log | more_stuff

utility >output.log      | more_stuff

In the first pipeline, more_stuff would get what's originally the standard error stream from utility as its standard input data, while in the second pipeline, since it's only the resulting standard output stream that is ever sent across a pipe, the more_stuff part of the pipeline would get nothing to read on its standard input.

  • With the command "utility 2>&1 | tee output.log, do you mean to say that since 1 is being directed to tee, 2 is as well. Since tee duplicates the stream, the output is both displayed on the console as well as written to file? Hence the difference between utility 2>&1 > output.log and utility 2>&1 | tee output.log is tee in that it duplicates the stream. Would that be correct? – Motivated Jan 21 at 16:09
  • With the examples of utility 2>&1 > output.log | more_stuff and utility >ouput.log | more_stuff, is the difference that more_stuff` has the standard error output to the console as an input more_stuff? Since in the second example, there is no output to the the console, there is essentially no input to more_stuff? If yes, that isn't clear since the preceding paragraph you note that standard output goes to the file and standard error goes to the console. – Motivated Jan 21 at 16:17
  • @Motivated Your first comment seems correct to me, yes. As for the second comment: In the first command, more_stuff would receive what utility originally sent to its error stream (but which was redirected to the standard output). Not because it would end up on the console if more_stuff wasn't there, but because it's going to the standard output stream. In the second command, more_stuff receives nothing as there is no standard output from the left hand side of the pipeline. The error stream from utility would still end up on the console in the 2nd command. – Kusalananda Jan 21 at 18:31
  • Thanks. Do you mean that because the command utility > output.log | more_stuff does not result in an output in the standard output stream from a standard error point of view? – Motivated Jan 22 at 5:48
  • @Motivated Since the left hand side doesn't produce anything on standard output (it's redirected), no data will be sent over the pipe. – Kusalananda Jan 22 at 8:29
4

The former outputs only to the file. The second outputs both to the file and to the screen.

4

The reason for 2>&1 | tee is to be able to capture both stdout and stderr to a log file and to see it on the screen at the same time. This could be done as >output.txt 2>&1 & tail -f as well, but you wouldn't know when the backgrounded command terminated - is the program terminated or is it running with no output. The 2>&1 | tee was a common idiom for programmers.

  • Do you mean to say that 2>&1 > file.txt for example would not capture both stdout and stderr to file.txt? – Motivated Jan 21 at 7:28
0

Let's see some sample code first:

#include <stdio.h>
main() 
{
// message 1, on stdout (using  printf)
printf("%s",          "message 1, on stdout (using  printf)\n");

// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");

// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}

Lets compare the results:
./helloerror
+ file: no message; console: message 1,2,3;

./helloerror >error.txt
+ file: message 1,2; console: message 3;

./helloerror 2>&1 >error.txt
+ file: message 1,2; console: message 3;
+ same as ./helloerror >error.txt

./helloerror >error.txt 2>&1
+ file: message 3,1,2; console: no message;
+ note the order 3 is first, then 1, then 2

./helloerror | tee error.txt 2>&1
+ file: message 1,2; console: message 3,1,2;
+ note the order 3 is first, then 1, then 2

./helloerror 2>&1 | tee error.txt
+ file: message 3,1,2; console: message 3,1,2;

To use:
./helloerror >error.txt 2>&1
-> if one wants all(stdout+stderr) messages in file, but not pinted on console

./helloerror 2>&1 | tee error.txt
-> if one wants all(stdout+stderr) messages in file and printed on console

-1

Here is a post summarizing Unix output streams: http://www.devcodenote.com/2015/04/unix-output-streams.html

A snippet from the post:

There are 3 standard output streams:

STDIN - Standard Input - Writes from an input device to the program
STDOUT - Standard Output - Writes program output to screen unless specified otherwise.
STDERR - Standard Error Output - Writes error messages. Also printed to the screen unless specified otherwise.

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.