What is the purpose of 'tee'?
What you don't see is that do_something | tee -a logfile
puts the output into logfile
and to stdout, while do_something >> logfile
puts it only into the logfile.
The purpose of tee
is to produce a one input, multiple output scenario - just like in a 'T' crossing.
EDIT
There have been comments around how tee
enables more seemless use of sudo
. This is beside the point: cat
, dd
or maybe better buffer
provide this possibility with better performance, if you don't need the multiple outputs. Use tee
for what it is designed, not for what it "can also do"
Tee
is not useless
Maybe you knew that anyway? If not, read on! Or if you know how it works, but aren't sure why it exists, skip to the end to see how it fit in the with the Unix philosophy.
What is the purpose of tee
?
At its simplest, it takes data on standard input and writes that to standard output and one (or more) files. It has been likened to a plumbing tee piece in the way it splits one input into two outputs (and two directions).
Examples
Let's take your first example:
do_something | tee -a logfile
This takes the output of do_something
and appends it to logfile, while also displaying it to the user. In fact, the Wikipedia page on tee
has this as the second example:
To view and append the output from a command to an existing file:
lint program.c | tee -a program.lint
This displays the standard output of the lint program.c command at the computer and at the same time appends a copy of it to the end of the program.lint file. If the program.lint file does not exist, it is created.
The very next example has another use: escalation of permissions:
To allow escalation of permissions:
cat ~/.ssh/id_rsa.pub | ssh admin@server "sudo tee -a /root/.ssh/authorized_keys2 > /dev/null"
This example shows tee being used to bypass an inherent limitation in the
sudo
command.sudo
is unable to pipe the standard output to a file. By dumping its standard out stream into/dev/null
, we also suppress the mirrored output in the console. The command above gives the current user root access to a server over ssh, by installing the user's public key to the server's key authorization list.
Or perhaps you want to take the output of one command, write that somewhere and also use that as input to another command?
You can also use tee command to store the output of a command to a file and redirect the same output as an input to another command.
The following command will take a backup of the crontab entries, and pass the crontab entries as an input to sed command which will do the substitution. After the substitution, it will be added as a new cron job.
$ crontab -l | tee crontab-backup.txt | sed 's/old/new/' | crontab –
(credit to Tee command usage examples)
Tee
works with the Unix philosophy:
Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.
(Credit to Basics of the Unix Philosophy)
tee
fits all of these:
- it does one thing: creates an extra copy of input
- it works with other programs because it is the glue (or a 'T' plumbing piece if you prefer) that lets other programs work together as in the examples above
- it does this by manipulating a text stream given on standard input
It's practically the same and it takes less keyboard hits to type out.
It is not the same at all...
The following appear to be somewhat equivalent, but they're not:
$ echo "hi" > test.txt
$ echo "hi" | tee test.txt
hi
The critical difference is that the former has written the data only to the named file, while the latter has written hi
to the terminal (stdout
) and the named file, as shown below:
tee
allows you to write the data to a file and use it in an onward pipeline, allowing you to do useful things - like keeping data from partway through a pipeline:
grep '^look ' interesting_file.txt \
| tee interesting_lines.txt \
| sort
Or, you can write to a file with elevated privileges, without giving the whole pipeline elevated privileges (here echo
and the shell are running as the user, while tee
writes to the file as root
):
echo 0 \
| sudo tee /proc/sys/net/ipv4/ip_forward
With tee
, you can write to many files (and stdout
):
echo "hi" \
| tee a.txt b.txt
It's also possible to use exec
with tee
to record all of a script's output to a file, while still allowing an observer (stdout
) to see the data:
exec > >( tee output.log )
This is a tee:
A T-shaped pipe fitting. It has an inlet, and two separate outlets.
In other words, it splits one pipe into two; like a fork in the road.
Similarly, tee
is a pipe (|
) that allows you to redirect your standard input to two separate outputs.
Example
Say for instance, you type ls /
.
You'll get an output that looks something like:
Applications Network Users bin dev net private tmp var
Library System Volumes cores etc home opt sbin usr
Redirect the output to a text file, ls / > ls.txt
, and no output is displayed in the shell, only in the resulting text file.
Want to see the output, AND pass it to a text file at the same time?
Add a tee
to your pipe (|
) ie: ls / | tee ls.txt
Compare the two:
ls / > ls.txt
ls / | tee ls.txt
No. You happen to mention one of the few examples where you could indeed redirect to the file using >
and >>
operators.
But Tee can do much more. Because you pipe to it, you can then pipe to something else.
A good example is listed on the wikipedia page:
find "4DOS" wikipedia.txt | tee 4DOS.txt | sort > 4DOSsorted.txt
Basically, you can pipe to Tee, so you can then pipe from Tee to something else. If all you want to do is write a log file, yes, then you don't really need Tee.