Introduction
The redirections and file descriptors are essential when working with the command-line interface. Knowing how I/O streams work helps you understand redirections even better.
In this article, you'll learn how to redirect stdout/stderr to a file in Bash.
Standard I/O Streams
When a command executes in Bash and other Linux shells, it uses three standard I/O streams. These I/O streams represent a system that allows programs to exchange data with their environment through input and output operations.
The standard I/O streams are:
- 0 -The standard input stream (stdin).
- 1 - The standard output stream (stdout).
- 2 - The standard error stream (stderr).
Each stream has assigned a numeric value, a file descriptor that helps operating systems keep track of open files.
0 - stdin: Standard Input Stream
Standard input (stdin) is a data stream from which a program reads. It is associated with the keyboard or a pipe in the case of an interactive shell.
The standard input stream is inherited from the parent process. This means the child process reads its input from the same source as the parent process. However, the standard input can also be explicitly redirected.
The file descriptor for standard input is 0 because standard input is the first file opened when a process starts.
Commands like ls or whoami don't require standard input. They accept command-line arguments but read the input from the current working directory and the operating system.
The ls
command, by default, lists the current working directory contents:
ls
In this case, there is no need to provide standard input.
The whoami
command prints the current user's username. It does not need any input from the user:
whoami
However, other commands like echo, man, or read
use standard input.
For instance, man
only provides detailed info about the command if a user inputs a command name in the stdin.
For example, get the cat manual page with:
man cat
Moreover, the echo
utility prints the text provided in the standard input as well:
echo "This is a sentence!"
stdin in Scripts
The difference between providing data via the command line and standard input is more noticeable in scripts. For instance, write a new script in a text editor of choice:
1. Create a script called script1.sh in Vim with:
vim script1.sh
Note: Always save script files with the sh extension.
2. Paste the following:
#!/bin/bash<br>read command<br>man $command
3. Save and exit the file.
4. Run the script with:
bash script1.sh
5. Provide the command name the script asks via stdin:
For example, usermod:
The script uses the stdin of usermod
to print the manual page for the command.
This script uses read
to request a command name via the standard input. Next, the input is used by man
to print the manual page.
1 - stdout: Standard Output Stream
Standard output (stdout) is a stream where a program writes output data. The program asks for data transfer with the write operation. The file descriptor for stdout is 1.
The standard output stream is associated with the terminal where the program is running. This means the terminal shows the program output. However, the standard output stream can be redirected to a file or another device.
Not all commands have stdout. For example, commands to create, move, or delete files do not generate any output unless there is an error.
For instance, mkdir, which creates a new directory, has no output:
mkdir directory1
2 - stderr: Standard Error Stream
Standard error (stderr) is a data stream that facilitates communication between a program and its environment. It provides a distinct channel to manage and display error messages separately from the standard output. The stderr initiates data transfers using the write operation, and the file descriptor for standard error is 2.
In most command-line environments, the standard error is used with standard output for a comprehensive program behavior overview. stdout and stderr are printed together in the terminal but often separated or shown in different colors. This segregation of normal output and error messages enables users to understand better the nature of issues a program encounters during its execution.
For example, to see both the stdout and stderr, run ls
for two directories (the existing Home directory, and the newdirectory, which doesn't exist on the system).
ls ./ newdirectory
The output prints:
- The error message ls: cannot access 'newdirectory': No such file or directory - an example of stderr.
- The Home directory contents - examples of stdout.
Redirecting stdout and stderr
Redirection is a way to use one program's output as input to another file or program. In most cases, streams are redirected to files or other streams using n>. The n operator represents the file descriptor number.
Redirect stdout and stderr to a File
To redirect a command's stdout and stderr to a file, use &>
without operators:
command &> [file_name]
For example, the command ls ./ newdirectory
lists the current directory contents and the error message in the terminal.
However, run the command to redirect stdout and stderr to a file:
ls ./ newdirectory &> complete_output
The terminal shows no output because both stdout and stderr have been redirected to the complete_output file.
Redirect stdout and stderr to Separate Files
Redirecting stdout and stderr to separate files enables users to review the output and error messages individually without cluttering the terminal.
The syntax for redirecting stdout and stderr to separate files is:
command > [output_file_name] 2> [error_file_name]
The syntax includes:
command > [output_file_name]
- Redirecting stdout to the specified output file.2> [error_file_name]
- Redirecting stderr to the specified file.
For example, run the command:
ls ./ newdirectory > output 2> error
The terminal shows no output because:
- Regular
ls
stdout is redirected to the output file. - Error message related to newdirectory not existing is redirected to the error file.
Verify by checking the file in the current directory:
Each file contains different output parts. The cat
command does the same:
Redirect stderr to stdout
It is common to redirect stderr to stdout to consolidate them into a single file for more straightforward analysis. The result is having error messages sent to the same location as standard output.
The syntax is:
command > [file_name] 2>&1
The command consists of:
> [file_name]
- Directs the stdout to the specified file.2>&1
- Redirects the stderr to the same location as the standard output.
For instance, redirect the ls ./ newdirectory
stdout to the results file and stderr to the same location with:
ls ./ newdirectory > results 2>&1
The output is once again excluded from the terminal but is present in the results file:
cat results
The order in the redirection command is crucial. For instance, the command in the following syntax only redirects the standard output to the file. The stderr gets redirected to the terminal.
The problematic syntax is:
command 2>&1 > [file_name]
The issue is:
2>&1
- Redirects stderr to the same location as stdout. However, since stdout has not been redirected yet in this syntax, stderr remains directed to the terminal.> [file_name]
- Redirects stdout to the specified file.
For instance, run:
ls ./ newdirectory 2>&1 > results1
The terminal shows the error message.
The results1 file contains only the stdout.
Redirect stdout to a File
To redirect only standard output to a file, run:
command 1> [file_name]
For instance:
ls ./ newdirectory 1> out1
The terminal prints the error message, but the stdout is redirected to out1.
Verify the results with:
cat out1
An even simpler option is to omit the number, as the command defaults to the standard input stream:
command > [file_name]
For instance, run:
ls ./ newdirectory > out2
The results are the same.
Redirect stderr to a File
To redirect the stderr to a file, use 2>
:
command 2> [file_name]
For instance:
ls ./ newdirectory 2> err1
The cat
command verifies the stderr is in the err1 file. However, the stdout is printed in the terminal.
Conclusion
After reading this article, you know what standard input streams are and how to redirect stdout and stderr to file in Bash.
Next, learn how to use the Linux exec command.