When bash initialises it opens three file descriptors for STDIN, STDOUT and STDERR:
0 = STDIN --> /dev/tty0
1 = STDOUT --> /dev/tty0
2 = STDERR --> /dev/tty0
File descriptors always point to a file and the case of the three above, that is your terminal, typically /dev/tty0
. It’s worth noting that you can create (or open) new file descriptors and you can redirect existing ones.
Line by Line Redirection
We can capture the output of some_command by using either:
$ some_command >file_name
or more explicitly by using the STDOUT file descriptor:
$ some_command 1>file_name
This has the affect of changing the file that the descriptor points to:
0 = STDIN --> /dev/tty0
1 = STDOUT --> file_name
2 = STDERR --> /dev/tty0
You can redirect STDERR using:
$ some_command 2>file_name
In fact you can redirect any file descriptor (n) to file_name using:
$ some_command n>file_name
Redirect STDOUT and STDERR to a file
The shortcut way to achieve this is:
$ some_command &>file_name
but using file descriptors explicitly we would achieve this by redirecting both streams to the same destination:
$ some_command >file_name 2>&1
This works by first redirecting STDOUT to the new file called file_name, then STDERR is duplicated to be the same as STDOUT. So the file descriptors now look like:
0 = STDIN --> /dev/tty0
1 = STDOUT --> file_name
2 = STDERR --> file_name
The order is super important. Using $ some_command 2>&1 >file_name
will not have the desired effect. To understand why, check out Bash One Liners Explained.
Redirect Multiple Script Lines to a Log File
This is particulalrly useful when you want to capture the output (or errors) from running multiple commands within a script. No one has time to redirect line by line….
To capture all errors only:
$ exec 2>file_name
bad_command # Error message sent to file_name
echo "Howdy" # Howdy sent to STDOUT
bad_command # Error message appended to file_name
To capture all errors and standard output:
$ exec >file_name 2>&1 # or exec &>file_name
bad_command # Error message sent to file_name
echo "Howdy" # Howdy appended to file_name
bad_command # Error message appended to file_name
Discard STDOUT
If /dev/tty0
is the terminal /dev/null
ia some other special file that just gets discarded. If for some reason you don’t want to be bothered by terminals verbosity you can just choose to ignore it with:
$ some_command > /dev/null
If you want to feel super powerful try:
$ some_command > /dev/null 2>&1
or $ some_command &> /dev/null
which will ignore standard output and error messages.
Comments