Linux tee Command

Read from stdin and write to stdout and files - 10 Practical Examples with Detailed Explanations

Example 1

Basic Usage - Write to File and Display

$ echo "Hello World" | tee output.txt
Hello World $ cat output.txt Hello World
Reads from standard input and writes to both standard output (your screen) and one or more files simultaneously. The command displays the text and saves it to output.txt at the same time. This is the fundamental use of tee - creating a "T" junction in your data stream.
Analogy: Like a T-shaped pipe fitting that splits water flow into two directions
Example 2

Append to File Instead of Overwriting

$ echo "Second line" | tee -a output.txt
Second line $ cat output.txt Hello World Second line
Appends to a file instead of overwriting it using the '-a' option. Without -a, tee overwrites the file. With -a, it adds to the end. Essential when you want to accumulate output over multiple commands without losing previous content.
Remember: -a for append, just like with redirect (>>)
Example 3

Write to Multiple Files Simultaneously

$ ls -la | tee file1.txt file2.txt file3.txt
total 48 drwxr-xr-x 5 user user 4096 Oct 18 10:30 . drwxr-xr-x 20 user user 4096 Oct 18 09:15 .. -rw-r--r-- 1 user user 220 Oct 18 10:30 file1.txt # Same output saved to file1.txt, file2.txt, and file3.txt
Writes the same input to multiple files at once. Just list all the filenames as arguments. Perfect for creating backups, distributing logs to different locations, or saving data in multiple formats simultaneously.
Use Case: Creating simultaneous backups in different directories
Example 4

Capture Command Output While Viewing

$ sudo apt update | tee apt-update.log
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease Get:2 http://security.ubuntu.com/ubuntu jammy-security InRelease Fetched 2,345 kB in 3s (780 kB/s) # Output displayed on screen AND saved to apt-update.log
Captures long-running command output to a log file while still displaying it on screen. This is invaluable for system updates, installations, or any command where you want to watch progress in real-time but also keep a record for later review or troubleshooting.
Best Practice: Always log system administration commands for audit trails
Example 5

Use with sudo to Write to Protected Files

$ echo "127.0.0.1 myhost" | sudo tee -a /etc/hosts
127.0.0.1 myhost $ tail -1 /etc/hosts 127.0.0.1 myhost
Writes to files requiring root permissions. Since 'sudo echo' doesn't work for redirecting to protected files, use tee with sudo instead. This is one of the most important tee use cases - properly writing to system files that need elevated privileges.
Why This Works: sudo applies to tee (which does the writing), not just echo
Example 6

Ignore Interrupts with -i Option

$ long-running-process | tee -i output.log
# Process continues even if you press Ctrl+C # Output continues to be captured
Makes tee ignore interrupt signals (like Ctrl+C) using the '-i' option. This ensures that data continues to be written even if the tee process receives an interrupt signal. Useful in scripts where you want to guarantee output capture regardless of signals.
Use Case: Critical logging where data loss from interrupts is unacceptable
Example 7

Combine with Grep for Filtered Logging

$ tail -f /var/log/syslog | tee full.log | grep ERROR > errors.log
# All logs saved to full.log # Only ERROR lines saved to errors.log # Everything displayed on screen
Creates a pipeline where tee saves complete output to one file while filtered output goes to another. The full log stream is preserved while also creating a filtered subset. Perfect for real-time monitoring with simultaneous full and filtered logging.
Real-World: Monitor logs in real-time, save everything, but also capture errors separately
Example 8

Timestamped Logging

$ ping google.com | while read line; do echo "$(date '+%Y-%m-%d %H:%M:%S') $line"; done | tee ping.log
2025-10-18 10:45:23 PING google.com (142.250.185.46): 56 data bytes 2025-10-18 10:45:23 64 bytes from 142.250.185.46: icmp_seq=0 ttl=117 time=12.3 ms 2025-10-18 10:45:24 64 bytes from 142.250.185.46: icmp_seq=1 ttl=117 time=11.8 ms # All output timestamped and logged
Adds timestamps to each line of output before logging with tee. Combines command output with date information to create time-stamped logs. Essential for debugging time-sensitive issues or analyzing when events occurred.
Debugging: Timestamps make troubleshooting much easier by showing when events happened
Example 9

Save stderr and stdout Separately

$ command 2>&1 | tee full.log
# Both stdout and stderr displayed and saved to full.log $ command > >(tee stdout.log) 2> >(tee stderr.log >&2)
Captures both standard output and standard error. The first example combines them (2>&1) before tee. The second example uses process substitution to send stdout and stderr to separate files while still displaying both. Critical for comprehensive logging of command execution.
Advanced: Process substitution >(command) treats command as a file for redirection
Example 10

Create Log with Command Pipeline

$ ./deployment-script.sh 2>&1 | tee -a deployment-$(date +%Y%m%d-%H%M%S).log
Starting deployment... Checking prerequisites... Deploying application... Deployment successful! # Saved to deployment-20251018-104523.log
Creates timestamped log files for important operations like deployments. Combines date command in filename with tee for automatic log naming. The 2>&1 captures both stdout and stderr, -a appends if script runs multiple times, and the dated filename prevents overwriting previous logs.
Production Use: Essential pattern for deployment scripts and automated maintenance
Bonus

Practical Script Example

#!/bin/bash # Backup script with logging LOGFILE="backup-$(date +%Y%m%d).log" { echo "=== Backup started at $(date) ===" # Run backup commands tar -czf /backup/data.tar.gz /data 2>&1 echo "=== Backup completed at $(date) ===" echo "=== Backup size: $(du -h /backup/data.tar.gz | cut -f1) ===" } | tee -a "$LOGFILE"
=== Backup started at Sat Oct 18 10:45:23 EDT 2025 === tar: Removing leading '/' from member names /data/file1.txt /data/file2.txt === Backup completed at Sat Oct 18 10:47:15 EDT 2025 === === Backup size: 2.3G === # Output displayed on screen AND appended to backup-20251018.log
A complete example showing how to use tee in production scripts. Groups multiple commands with curly braces, pipes everything through tee to create comprehensive logs. This pattern ensures you can watch progress while maintaining a permanent record.
Best Practice: Use this pattern for all important maintenance and backup scripts
Reference

Common tee Usage Patterns Quick Reference

Basic Usage: command | tee file.txt Write to file and screen command | tee -a file.txt Append to file and screen command | tee file1 file2 file3 Write to multiple files Common Patterns: sudo command | tee log.txt Regular command with logging echo "text" | sudo tee -a /etc/file Write to protected file command 2>&1 | tee log.txt Capture stdout and stderr command | tee >(process) Split stream to process Filtering: cmd | tee full.log | grep ERROR Save all, display filtered cmd | tee -a all.log | grep WARN > warn.log Multiple logs Timestamping: cmd | while read line; do echo "$(date) $line"; done | tee log cmd | ts | tee log.txt (using moreutils 'ts') Script Logging: { # Multiple commands command1 command2 } | tee -a script.log exec > >(tee -a logfile.log) Redirect all script output exec 2>&1 Include stderr in redirection System Administration: echo "config" | sudo tee /etc/file Write to system file apt update | tee apt-update.log Log package manager ./deploy.sh 2>&1 | tee deploy.log Log deployment Options: -a Append instead of overwrite -i Ignore interrupt signals --output-error=MODE Error handling (warn, warn-nopipe, exit, exit-nopipe) Common Combinations: command | tee -a logfile.log | grep ERROR | tee errors.log sudo sh -c 'command | tee /protected/file' command 2>&1 | tee >(logger -t mytag)
A comprehensive reference of tee usage patterns for various system administration and logging scenarios. These patterns are essential for maintaining proper audit trails and debugging capabilities.