Unix: tee

I’ve read about the Unix ‘tee‘ command before but never found a reason to use it until the last few weeks.

One of the things I repeatedly do by mistake is open /etc/hosts without sudo and then try to make changes to it:

$ vi /etc/hosts
# Editing it leads to the dreaded 'W10: Changing a readonly file'

I always used to close the file and then re-open it with sudo but I recently came across an approach which allows us to use ‘tee’ to get around the problem.

Once we’ve made our change we can run the following command:

:w !sudo tee %

The ‘:w’ is usually used to write the buffer to the current file but here we’re substituting a shell command to receive the buffer instead.

In this case we’re sending the buffer to the ‘sudo tee %’ command where ‘%’ refers to the current file name.

tee is defined like so:

The tee utility copies standard input to standard output, making a copy in zero or more files. The output is unbuffered.

So we’re sending the buffer for the current file to tee which then saves it to the current file. Since we’ve run tee with sudo it will give us the appropriate permissions to write to the file that we didn’t initially have.

This Stack Overflow post explains what’s going on in more detail.

Another thing we’ve been working on is hooking up the logs of our various services to logstash and to test it out we needed to write to files in the /var/log directory.

We started out trying to echo a message to the end of the apache log file like this:

$ echo "random message" >> /var/log/apache2/access_log 
zsh: permission denied: /var/log/apache2/access_log

As you can see that doesn’t work since we don’t have permissions to write to files in /var/log so we need to find another way to do that and Nick pointed out that tee would do the job here as well.

$ echo "random message" | sudo tee -a /var/log/apache2/access_log
random message

Passing the ‘-a’ flag to tee means that it appends standard input to the file instead of replacing the whole file like before. If we don’t want standard in to be directed to standard out we can redirect that to /dev/null like so:

$ echo "random message" | sudo tee > /dev/null -a /var/log/apache2/access_log
Be Sociable, Share!