Streams
Overview
Teaching: 15 min
Exercises: 5 minQuestions
What are the standard output streams?
How can I redirect them?
Objectives
Understand the difference betwen STDERR and STDOUT.
Split STDOUT and STDERR output with 2> and 1> redirects.
Use the
tee
command to redirect to a file and the screen.
There are three standard input/outputs streams created when you run a Unix command. These can be thought of as the transfer of data to and from your command. The three streams are standard input (STDIN), standard output (STDOUT) and standard error (STDERR).
To explore these streams, we’re going to use Nelle’s do-stats.sh script from earlier. Therefore, return to the north-pacific-gyre
directory.
STDIN
STDIN is the stream by which the program you are running is provided with its input data. Unix automatically connects this to your terminal keyboard. For example, when you are entering your password or passphrase when ssh-ing into a remote server, you are using STDIN. The stream ID of STDIN is 0.
STDOUT vs STDERR
STDOUT and STDERR are both connected to your terminal screen. STDOUT is the stream used by the program you are running for its output data and STDERR is the stream for any error messages or diagnostics such as log messages.
For example,
bash do-stats.sh 2012-07-03/NENE01812A.txt
results in
2012-07-03/NENE01812A.txt
being printed to the terminal. This is because we used echo
in do-stats.sh
- by default, echo uses the output stream.
If we make a typo and run
bash do-stat.sh 2012-07-03/NENE01812A.txt
we get
bash: do-stat.sh: No such file or directory
printed to the terminal. This is actually using the error stream, but because STDOUT and STDERR are both automatically displayed by your terminal, it might not immediately be obvious that these two streams are different.
However, they can be separated. This means that you can stop error messages and warnings being mixed in with your output.
2>
and 1>
redirects
Let’s remind ourselves of how to redirect the output from a command to a text file (as we saw in the Introduction to Unix Shell workshop), uing the >
symbol.
bash do-stats.sh 2012-07-03/NENE01812A.txt > output.txt
Now there is nothing printed to the screen, because our output is being redicted to a file named output.txt
.
cat output.txt
2012-07-03/NENE01812A.txt
Let’s repeat this, but, this time, use our command with a typo from before that we know will generate an error.
bash do-stat.sh 2012-07-03/NENE01812A.txt > output.txt
bash: do-stat.sh: No such file or directory
In this case, the error is still printed to the terminal, because >
, by default, redirects STDOUT, not STDERR.
However, >
can be used to redirect STDERR, or both STDOUT and STDERR. Putting a number in front of the >
controls which stream it redirects. 1
is the stream ID of STDOUT, so 1>
is the same as >
.
bash do-stats.sh 2012-07-03/NENE01812A.txt 1> output.txt
To redirct STDERR, use a stream ID of 2, i.e. 2>
.
bash do-stat.sh 2012-07-03/NENE01812A.txt 2> error.txt
cat error.txt
bash: do-stat.sh: No such file or directory
It is also possible to redirect both the output and error streams at once. In order to see this, let’s try running do-stats.sh
on a file that we know does not exist.
bash do-stats.sh 2012-07-03/NENE01812C.txt
2012-07-03/NENE01812C.txt
head: cannot open '2012-07-03/NENE01812C.txt' for reading: No such file or directory
If you want both streams redirected to the same file you can do:
bash do-stats.sh 2012-07-03/NENE01812C.txt > output-and-error.txt 2>&1
cat output-and-error.txt
2012-07-03/NENE01812C.txt
head: cannot open '2012-07-03/NENE01812C.txt' for reading: No such file or directory
This redirects STDOUT to a text file as before, then 2>&1
redirects STDERR to wherever STDOUT is being redirected to.
Redirecting STDOUT and STDERR to different files
Our initial aim was to redirect STDERR and STDOUT to two different files, in order to seperate any warnings or diagnostic errors from our program output. Can you work out how Nelle can do this when running
bash do-stats.sh 2012-07-03/NENE01812C.txt
?Solution
bash do-stats.sh 2012-07-03/NENE01812C.txt > output.txt 2> error.txt
cat output.txt
2012-07-03/NENE01812C.txt
cat error.txt
head: cannot open '2012-07-03/NENE01812C.txt' for reading: No such file or directory
The tee
command
The Unix command tee
duplicates STDOUT and sends the second copy to a file.
Consider the input/output stream model we’ve already discussed as a system of pipes.
tee
sensibly splits the flow of information, allowing one copy to be written
to disk and leaving one copy available for a subsequent command in the chain.
bash do-stats.sh 2012-07-03/NENE*.txt | tee output.txt
2012-07-03/NENE01729A.txt
2012-07-03/NENE01729B.txt
2012-07-03/NENE01736A.txt
2012-07-03/NENE01751A.txt
2012-07-03/NENE01751B.txt
2012-07-03/NENE01812A.txt
2012-07-03/NENE01843A.txt
2012-07-03/NENE01843B.txt
2012-07-03/NENE01971Z.txt
2012-07-03/NENE01978A.txt
2012-07-03/NENE01978B.txt
2012-07-03/NENE02018B.txt
2012-07-03/NENE02040A.txt
2012-07-03/NENE02040B.txt
2012-07-03/NENE02040Z.txt
2012-07-03/NENE02043A.txt
2012-07-03/NENE02043B.txt
cat output.txt
2012-07-03/NENE01729A.txt
2012-07-03/NENE01729B.txt
2012-07-03/NENE01736A.txt
2012-07-03/NENE01751A.txt
2012-07-03/NENE01751B.txt
2012-07-03/NENE01812A.txt
2012-07-03/NENE01843A.txt
2012-07-03/NENE01843B.txt
2012-07-03/NENE01971Z.txt
2012-07-03/NENE01978A.txt
2012-07-03/NENE01978B.txt
2012-07-03/NENE02018B.txt
2012-07-03/NENE02040A.txt
2012-07-03/NENE02040B.txt
2012-07-03/NENE02040Z.txt
2012-07-03/NENE02043A.txt
2012-07-03/NENE02043B.txt
Where might this be useful? For instance, you can use this to both passively log and actively monitor a compilation or a data processing step.
Because tee
preserves STDOUT, it allows recovery from actions that overwhelm
the buffer of your shell’s window as well, which is often limited.
Key Points
STDERR can be redirected by using 2>.
STDOUT can be redirected by using 1> or >.
tee can be used to duplicate STDOUT and send the second copy to a file.