Shell: redirect stdout to /dev/null and stderr to stdout [duplicate]
I saw this interesting question at a comment on cyberciti.biz. That I found I even can’t find a flexible way to do this in one-line command with sh. As far my thought for the solution is:
tmp_file=`mktemp` (./script 2>$tmp_file >/dev/null; cat $tmp_file) | ./other-script rm tmp_file
But you see, this is not synchronous, and fatally, it’s so ugly. Welcome to share you mind about this. 🙂
@cnicutar It seemed I have a wrong understanding in the start. I supposed 2>&1 will redirect stderr to stdout and the 1>/dev/null will then redirect both them into /dev/null . Well I need to relearn some shell.
3 Answers 3
./script 2>&1 1>/dev/null | ./other-script
The order here is important. Let’s assume stdin (fd 0), stdout (fd 1) and stderr (fd 2) are all connected to a tty initially, so
0: /dev/tty, 1: /dev/tty, 2: /dev/tty
The first thing that gets set up is the pipe. other-script’s stdin gets connected to the pipe, and script’s stdout gets connected to the pipe, so script’s file descriptors so far look like:
Next, the redirections occur, from left to right. 2>&1 makes fd 2 go wherever fd 1 is currently going, which is the pipe.
Lastly, 1>/dev/null redirects fd1 to /dev/null
0: /dev/tty, 1: /dev/null, 2: pipe
End result, script’s stdout is silenced, and its stderr is sent through the pipe, which ends up in other-script’s stdin.
Also note that 1>/dev/null is synonymous to, but more explicit than >/dev/null
How to Redirect Output to /dev/null in Linux
In Linux, programs are very commonly accessed using the command line and the output, as such, is displayed on the terminal screen. The output consists of two parts: STDOUT (Standard Output), which contains information logs and success messages, and STDERR (Standard Error), which contains error messages.
Many times, the output contains a lot of information that is not relevant, and which unnecessarily utilizes system resources. In the case of complex automation scripts especially, where there are a lot of programs being run one after the other, the displayed log is huge.
In such cases, we can make use of the pseudo-device file ‘/dev/null‘ to redirect the output. When the output is redirected to /dev/null, it is immediately discarded, and thus, no resource utilization takes place.
Let’s see how to redirect output to /dev/null in Linux.
Let us take an example of the mv command trying to move two files to a particular directory, where one file is moved successfully (displays STDOUT) and the other gives an error while moving (displays STDERR).
$ mv -v tmp.c /etc/apt/sources.list /tmp
Note: The ‘-v’ argument to mv displays the success log when a file is moved. Without the flag, nothing is printed to STDOUT.
Now, to redirect only the STDOUT to /dev/null, i.e. to discard the standard output, use the following:
$ mv -v tmp.c /etc/apt/sources.list /tmp 1>/dev/null
What does ‘1>/dev/null’ mean?
Here ‘1’ indicates STDOUT, which is a standard integer assigned by Linux for the same. The operator ‘>’ , called a redirection operator, writes data to a file. The file specified in this case is /dev/null. Hence, the data is ultimately discarded.
If any other file were given instead of /dev/null, the standard output would have been written to that file.
Similarly, to redirect only the STDERR to /dev/null, use the integer ‘2’ instead of ‘1’ . The integer ‘2’ stands for standard error.
$ mv -v tmp.c /etc/apt/sources.list /tmp 2>/dev/null
As you can see, the standard error is not displayed on the terminal now as it is discarded in /dev/null.
Finally, to discard both STDOUT and STDERR at the same time, use the following:
$ mv -v tmp.c /etc/apt/sources.list /tmp &>/dev/null
The ampersand character (‘&’) denotes that both the standard output and standard error has to be redirected to /dev/null and discarded. Hence, in the last screenshot, we do not see any output printed on the screen at all.
Conclusion
In this article, we have seen how to redirect output to /dev/null. The same can be used in either command or in complex Bash scripts which generate a heavy amount of log. In case if the script needs debugging, or has to be tested; in such cases, the log is required to view and analyze the errors properly.
However in cases when the output is already known and anticipated, it can be discarded with /dev/null. If you have any questions or feedback, let us know in the comments below!
redirecting to /dev/null
I’m trying to understand the use of /dev/null 2>&1 here. At first, I thought this script uses /dev/null in order to gracefully ignore errors, without causing the script to crash (kind of like try catch exception handling in programming languages). Because I don’t see how using tar to compress a directory into a tar file could possibly cause any type of errors.
Just a trick to avoid unnecessary output. As for why tar can cause errors: because the target directory does not exist, because the source doesn’t, because you don’t have write access to the target, or read to the source, because tar is not in your $PATH, because tar crashed (you never know), because there’s no space left on the device, because the tar version changed and now requires different syntax, because the disk caused an I/O error. I’m sure you could find more.
6 Answers 6
No, this will not prevent the script from crashing. If any errors occur in the tar process (e.g.: permission denied, no such file or directory, . ) the script will still crash.
This is because of using > /dev/null 2>&1 will redirect all your command output (both stdout and stderr ) to /dev/null , meaning no outputs are printed to the terminal.
stdin ==> fd 0 stdout ==> fd 1 stderr ==> fd 2
In the script, you use > /dev/null causing:
stdin ==> fd 0 stdout ==> /dev/null stderr ==> fd 2
stdin ==> fd 0 stdout ==> /dev/null stderr ==> stdout
Recommended: Use 2>& 1 in code examples to stress that the number and the ampersand are considered to be part of the redirection operator. It is common for redirection to a file to have a space between > and /path/to/file , redirection to a file descriptor is essentially the same thing.
@dbmikus You should have asked that as a separate question 🙂 Nevertheless, the first one says «redirect writes to file descriptor 1 to /dev/null , and then redirect writes to file descriptor 2 to the same place as the writes to file descriptor 1 are going» . The second one says «redirect writes to file descriptor 2 to the same place as the writes to file descriptor 1 are going, and then redirect writes to file descriptor 1 to /dev/null «. I also struggled with this. Idea from a coworker and from unix.stackexchange.com/a/497215/12428 for a detailed description.
To understand «redirecting to /dev/null » easily, write it out explicitly. Below is an example command that tries to remove a non-existent file (to simulate an error).
rm nonexisting.txt 1> /dev/null 2> /dev/null
Below are couple of enhancements.
Enhancement 1: You can replace 1> with just > . This is because 1 is the default stdout and you can ignore mentioning defaults.
rm nonexisting.txt > /dev/null 2> /dev/null
Enhancement 2: You can replace the 2nd file redirect ( > /dev/null ) with a file descriptor duplication ( >& 1 ). This is because /dev/null is already pointed to by stdout 1 .
rm nonexisting.txt 1> /dev/null 2>& 1
Enhancement 3: This is such a common operation, that many shells have a shortened form of this as a single &> operator.
rm nonexisting.txt &> /dev/null
My suggestion: Stick to the first option. Write out the commands explicitly instead of using pointers. Takes little to no extra effort but much easier to understand and explain.
this is actually quite the better answer, as it is a «this means that», rather than a generic «this does that»
Superb, I’ve been struggling to understand this topic for ages, finally I know how to use it. Explicit commands are the best way to explain and to memorize.
@thomp45793 Portability? Readability? __no __my __attribute__((cringe)) __code __looks __attribute__((allways_inline)) __like __this
I’m trying to understand the use of «> /dev/null 2>&1» here.
(note that I added the redirection before /dev/null in your question.)
The above would redirect the STDOUT and STDERR to /dev/null . It works by merging the STDERR into the STDOUT . (Essentially all the output from the command would be redirected to the null device.)
. without causing the script to crash (kind of like try catch exception handling in programming languages).
It’s not quite like a try/catch or anything. It simply silences any sort of output (including error) from the command.
Because I don’t see how using tar to compress a directory into a tar file could possibly cause any type of errors.
It could result in errors for a number of reasons, including:
- Inadequate permissions on the file(s) you’re attempting to archive or on the file that you’re attempting to write to
- Lack of disk space in order to create the archive
When you run CMD > /dev/null 2>&1
STDOUT redirects to /dev/null, and then STDERR redirects to THE ADDRESS of STDOUT, which has been set to /dev/null , consequently both STDOUT and STDERR point to /dev/null
Oppositely, when you run CMD 2>&1 >/dev/null
STDERR redirects to THE ADDRESS of STDOUT (File descriptor 1 in that moment, or /proc/self/fd/1), and then STDOUT redirects to /dev/null , but STDERR keeps redirecting to fd1!! As a result the normal output from STDOUT is discarded, but the errors coming from STDERR are still being written onto the console.
&> /dev/null did not work for me in a script file, outputting the whole stderr after the script is completed, but > /dev/null 2>&1 worked well.
cat nonexistantfile.txt &>/dev/null
This redirects both STDOUT both STDIN
And is equivalent to
cat nonexistantfile.txt >/dev/null 2>&1
Bash I/O Redirection
(file descriptor 1 is the default, so > is short for 1> )
redirects stderr and stdout to /dev/null . which means to nowhere. Things sent to /dev/null are not saved, cached, or remembered in any way.
They are just sent to ‘nowhere‘ and forgotten. This is a way of running programs and making sure they produce NO output and will never be seen on the command line or in a log file.
I see this type of question quite a bit . mainly because I’ve had to look it up myself since I haven’t been coding in years. Here is some handy information from the ABSG:
«Redirection simply means capturing output from a file, command, program, or script and sending it as input to another file, command, program, or script.»
2>&1 # Redirects stderr to stdout. command >>filename 2>&1 # Appends both stdout and stderr #+ to the file "filename" .
ABSG: Advanced Bash Scripting Guide: The Chapter 20 link above is a link to the I/O redirection page of the open source tldp.org document called the Advanced Bash Scripting Guide by Mendel Cooper. It is listed as «An in-depth exploration of the art of shell scripting » and I absolutely agree. It is a terrific resource and has tons of answers to all sorts of crazy situations.
Other Valuable Resources: There are many valuable resources in the current/maintained section (in several handy formats like html, pdf, text, etc) on the Linux Documentation Project Guides page. Here are a few I have found useful:
- Bash Guide for Beginners by Machtelt Garrels
- Introduction to Linux by Machtelt Garrels
- GNU/Linux Command-Line Tools Summary by Gareth Anderson
- Linux Filesystem Hierarchy by Binh Nguyen
- Securing & Optimizing Linux (pdf only): The Ultimate Solution by Gerhard Mourani