Tool tips: Tee (and standard streams)
Tee is a wonderful but often-overlooked core utility. It's purpose is to intercept a pipeline, write the output to a file, and pass the output along the pipe. It can be used to easily add output logging to any command pipeline or script.
To get the most out of tee, it pays to read up on how input, output, and errors are handled by the shell. (As a byproduct, a good understanding of bash I/O redirection will make you a more efficient bash user and scripter!)
There are three standard streams that can be used by any unix program: stdin, stdout, and stderr. Each of these can be thought of as a file. By default, all unix programs read from stdin, write normal output to stdout, and write error messages to stderr. The shell's job is to take things being read or written to one of the standard streams and redirect them through pipes that you specify. By default, the shell will take the characters you type into the terminal while a program is running and pass them to that program's stdin. It will take the characters written by the program to stderr and stdout and print them to your terminal.
If you instead insert a pipe, like so:
command1 | command2
the shell will redirect the characters written to command1's stdout to command2's stdin via a pipe. Command1's stderr will still get written to your terminal.
Bash has syntax for specifying custom redirections. For instance, you can redirect stdout to a file instead of your terminal:
command1 > file
This is where tee comes in. If we want to both log something to a file and pass it along a pipe, or just have it written to the terminal (by leaving tee as the last command in the pipe,) we can insert tee into our pipe:
command1 | tee file | command2
If you want to do something other than use tee to log just stdout, you should read more about bash I/O redirection. Here are some resources:
- Advanced Bash-Scripting Guide: A Detailed Introduction to I/O and I/O Redirection
- Advanced Bash-scripting guide: I/O Redirection
- Greg's Wiki: How can I redirect stderr to a pipe?
- Greg's Wiki: How can I redirect the output of multiple commands at once?
Typical invocation:
some command that produces output | tee file