4 min read

How to Log Script Output to a File AND See It in the Terminal

Table of Contents

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 to stderr.
  • &1 refers to stdout.
  • So, 2>&1 means “send stderr to the same destination as stdout”.

Here is the complete command:

./demo_script.sh 2>&1 | tee output.log

Now, when you run this command:

  1. All output, including the error message, will be displayed in your terminal.
  2. 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.