sh command: exec 2>&1 sh command: exec 2>&1 bash bash

sh command: exec 2>&1


Technically speaking it duplicates, or copies, stderr onto stdout.

Usually you don't need the exec to perform this. A more typical use of exec with file descriptors is to indicate that you want to assign a file to an unused file descriptor, e.g.

exec 35< my_input

BTW Don't forget that the sequence of declaration when piping to a file is important, so

ls > mydirlist 2>&1

will work because it directs both stdout and stderr to the file mydirlist, whereas the command

ls 2>&1 > mydirlist

directs only stdout, and not stderr, to file mydirlist, because stderr was made a copy of stdout before stdout was redirected to mydirlist.

Edit: It's the way that the shell works scanning from left to right. So read the second one as saying "copy stderr onto stdout" before it says "send stdout to mydirlist". Then read the first one as saying "send stdout to the file mydirlist" before it says "duplicate stderr onto that stdout I've set up". I know. It's totally not intuitive!


One of the better articles I've seen on what "2>&1" does is Bash One-Liners Explained, Part III: All about redirections.

But what the current answers on this question fail to provide is why you'd want to do this after a plain "exec". As the bash man page for the exec command explains: "If command is not specified, any redirections take effect in the current shell".

I wrote a simple script called out-and-err.py that writes a line of output to stdout, and another line to stderr:

#!/usr/bin/pythonimport syssys.stdout.write('this is stdout.\n')sys.stderr.write('this is stderr.\n')

And then I wrapped that in a shell script called out-and-err.sh with an "exec 2>&1":

#!/bin/bashexec 2>&1./out-and-err.py

If I run just the python script, stdout and stderr are separate:

$ ./out-and-err.py 1> out 2> err$ cat outthis is stdout.$ cat errthe is stderr.

But if I run the shell script, you can see that the exec takes care of stderr for everything after:

$ ./out-and-err.sh 1> out 2> err$ cat outthis is stdout.this is stderr.$ cat err$

If your wrapping shell script does a lot more than just the one python command, and you need all output combined into stdout, doing the "exec 2>&1" will make that easy for you.


It ties standard error to standard out

the 2 is stderr and 1 is stdout. When you run a program, you'll get the normal output in stdout, but any errors or warnings usually go to stderr. If you want to pipe all output to a file for example, it's useful to first combine stderr with stdout with 2>&1.