Mastering Linux Standard Stream Redirection with the tee Utility

The tee command acts as a splitter in a pipeline, reading from standard input and writing simultaneously to standard output and one or more files. Its core value is allowing operators to inspect a data stream in real time while preserving it for later processing or auditing.

command | tee [options] file [file2 ...]

Options Overview

  • -a, --append: Append data to files rather than overwriting them.
  • -i, --ignore-interrupts: Continue running even after receiving interrupt signals like SIGINT (Ctrl+C).
  • -p: Operate in a mode that ignores interrupts; functionally equivalent to -i.
  • -s, --silent: Suppress diagnostic messages such as errors or warnings about unwritable files.

When no file is specified, tee simply relays data from stdin to stdout.

Practical Workflows

Recording Terminal Activity

Executing a command and saving its output verbatim is one of the most common scenarios. The following example both displays build output and archives it:

make 2>&1 | tee build_$(date +%Y%m%d).log

The 2>&1 redirect ensures both standard error and standard output are captured.

Multicasting to Several Logs

Distributing a data stream across multiple files can be achieved without spawning extra tee processes. Use shell redirection to avoid duplication:

some_long_running_job | tee primary.log > secondary.log

This sends the stream to the terminal, primary.log, and secondary.log with a single tee invocation.

Selective Filtering with grep

Combining tee with grep lets you see all raw output while storing it, yet only display lines matching a pattern on the console:

ffmpeg -i input.mp4 output.avi 2>&1 | tee transcode.log | grep --color=auto 'frame='

The entire log ends up in transcode.log, but the terminal only highlights lines containing frame progress.

Inline Transformation with awk

Perform immediate field extraction without losing the original dataset:

ps aux | tee snapshot.txt | awk '$3 > 5.0 {print $2, $3, $11}'

A full snapshot of processes is saved to snapshot.txt, while the terminal displays only the PID, CPU%, and command name for processes consuming more than 5% CPU.

chaining sudo for Protected Files

Writing to privileged locations is possible by prepending sudo to the command that invokes tee. The pipe itself cannot elevate privileges, but tee can:

echo 'net.core.somaxconn=1024' | sudo tee /etc/sysctl.d/99-custom.conf

Apppending with Timestamps

Maintaining a chronological log with human-readable timestamps is straightforward:

some_process 2>&1 | while IFS= read -r line; do
    echo "[$(date '+%F %T')] $line"
done | tee -a timeline.log

Each line is stamped before being displayed and appended to timeline.log.

Resource and Performance Notes

When handling high-volume streams, tee's implicit write operations can become a bottleneck. Disk I/O throttling may slow down the pipeline. In such cases, evaluate whether the immediate terminal view is necessary; if not, a simple output redirect (command > file) eliminates the extra work. For minimal overhead, consider using stdbuf or unbuffer to adjust output buffering but always measure the impact on throughput.

Tags: Linux Shell TEE Command Line I/O Redirection

Posted on Wed, 29 Jul 2026 16:25:32 +0000 by ik