When running a bash script, especially a long or complex one, you often face a dilemma: do you watch the output in real-time in your terminal, or do you redirect it to a log file for later review? With standard redirection (>), you can only do one.
Fortunately, Linux provides a powerful command that lets you do both. This guide will show you how to see your script’s output on the screen and save a complete copy to a file using the tee command.
The Problem with Standard Redirection
Normally, you might save a command’s output like this:
./my_long_script.sh > output.log
This works, but it’s a “silent” operation. You won’t see any output in your terminal until the script finishes. For monitoring progress or catching immediate issues, this isn’t ideal.
The Solution: The tee Command
The tee command is the perfect tool for this job. Named after a T-splitter in plumbing, it reads from standard input and writes to both standard output (your terminal screen) and one or more files.
Let’s walk through how to use it.
Step 1: Create a Demo Script
First, let’s create a simple bash script to generate some output, including both standard messages and an error. Save the following content as demo_script.sh:
#!/bin/bash
echo "Starting the data processing..."
echo "Processing file: records.csv"
sleep 1
echo "Update: 50% complete."
# This command will fail and produce an error
ls /nonexistent/directory
sleep 1
echo "Script finished."
Make the script executable:
chmod +x demo_script.sh
Step 2: The Basic tee Command (stdout only)
The simplest way to use tee is to pipe your script’s output to it.
./demo_script.sh | tee output.log
When you run this, you’ll see the standard output messages appear in your terminal. However, you’ll also notice the error message (ls: cannot access...) only appears on the screen and is not saved to output.log.
This is because, by default, the pipe (|) only sends standard output (stdout) to the next command. The error message is sent to standard error (stderr).
Step 3: Capturing Both stdout and stderr
To log everything—both regular output and errors—we need to redirect stderr to stdout before piping to tee. The magic for this is 2>&1.
2>refers tostderr.&1refers tostdout.- So,
2>&1means “sendstderrto the same destination asstdout”.
Here is the complete command:
./demo_script.sh 2>&1 | tee output.log
Now, when you run this command:
- All output, including the error message, will be displayed in your terminal.
- An exact copy of that output will be saved to the file
output.log.
Step 4: Appending to a Log File
By default, tee will overwrite the contents of your log file every time you run the command. If you want to keep a running log, you can use the -a (or --append) flag.
./demo_script.sh 2>&1 | tee -a output.log
Run this command a few times. You’ll see that output.log grows with the output from each execution instead of being replaced.
Conclusion
You no longer have to choose between watching your script run and logging its output. By combining output redirection with the tee command, you get the best of both worlds.
The key command to remember is:
# General Syntax
your_command 2>&1 | tee logfile.txt
# To append instead of overwrite
your_command 2>&1 | tee -a logfile.txt
This simple but powerful pattern is an essential tool for any bash scripter, making debugging and monitoring automated tasks significantly easier. For a pro tip, consider adding a timestamp to your log file names (tee -a "log-$(date +%F).txt") to automatically create daily logs.