The tail command displays the last part of files or input from a pipeline. By default, it shows the last 10 lines, but this can be customized. One of its most powerful features is the ability to follow files in real-time (-f), making it indispensable for monitoring log files and tracking system activity.
Key Features:
Real-Time Monitoring Follow files as they grow
Flexible Output Lines or bytes from end of file
Multiple Files Monitor several files simultaneously
Pipe-Friendly Perfect for data pipelines
💡 Note: tail is part of GNU coreutils and is available on all Unix/Linux systems. The complement command is head, which displays the beginning of files.
Command Syntax
tail [OPTIONS] [FILE(s)]
Essential Options
Option
Description
Example
-n N
Show last N lines (default: 10)
tail -n 20 file.txt
-n +N
Start output at line N
tail -n +5 file.txt
-c N
Output last N bytes
tail -c 100 file.txt
-f
Follow file (real-time updates)
tail -f /var/log/syslog
-F
Follow with retry (survives rotation)
tail -F app.log
-q
Quiet (suppress headers)
tail -q file1 file2
-v
Verbose (always show headers)
tail -v file.txt
--pid=PID
With -f, terminate after PID dies
tail -f --pid=1234 log.txt
-s N
Sleep N seconds between iterations
tail -f -s 5 log.txt
Detailed Examples
Example 1: Display Last 10 Lines (Default)
cat << EOF > sample.txt
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
Line 12
EOF
tail sample.txt
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
Line 12
Without options, tail displays the last 10 lines:
Default behavior shows 10 lines from end of file
Perfect for quick preview of file endings
Commonly used to check recent log entries
If file has fewer than 10 lines, shows entire file
Example 2: Specify Number of Lines
tail -n 5 sample.txt
Line 8
Line 9
Line 10
Line 11
Line 12
Use -n to specify exact number of lines to display:
tail -n 5 or tail -5 - Last 5 lines
tail -n 100 - Last 100 lines
tail -n 1 - Just the last line
Alternative shorthand: tail -20 file.txt (without 'n')
💡 Pro Tip: Combine with wc -l to show percentage: tail -n $(( $(wc -l < file.txt) / 2 )) file.txt shows last half of file.
Example 3: Start from Specific Line (Skip Beginning)
tail -n +8 sample.txt
Line 8
Line 9
Line 10
Line 11
Line 12
The + prefix makes tail start at a specific line number:
echo "This is a test string with exactly 50 characters!" | tail -c 20
0 characters!
Use -c to work with bytes instead of lines:
tail -c 100 - Last 100 bytes
tail -c 1K - Last kilobyte (1024 bytes)
tail -c 1M - Last megabyte
Useful for binary files or examining file ends
📏 Size Suffixes: K (1024), M (1024²), G (1024³), T, P, E, Z, Y
Example 5: Follow File in Real-Time
# In one terminal, create growing log file
while true; do
echo "$(date '+%Y-%m-%d %H:%M:%S') - Log entry" >> app.log
sleep 2
done
# In another terminal, monitor it
tail -f app.log
The -f (follow) option is tail's most powerful feature:
Displays new lines as they're appended to file
Updates in real-time without reloading
Essential for monitoring active log files
Press Ctrl+C to stop following
Shows last 10 lines initially, then follows
🔥 Most Common Use:tail -f /var/log/syslog - Monitor system logs in real-time!
Example 6: Follow with File Rotation Support
tail -F /var/log/application.log
The -F option is like -f but handles log rotation:
Continues following even if file is renamed or deleted
Automatically reopens file when recreated
Perfect for rotated logs (logrotate, log4j rotation)
More robust than -f for production monitoring
📝 What Happens During Rotation:
# With tail -f (stops following after rotation)
mv app.log app.log.1
touch app.log # tail -f still watching app.log.1!
# With tail -F (automatically switches to new file)
mv app.log app.log.1
touch app.log # tail -F switches to new app.log!
#!/bin/bash
# Comprehensive log monitoring and analysis script
LOG_FILE="/var/log/application.log"
ERROR_COUNT=0
WARN_COUNT=0
echo "Starting log monitor for $LOG_FILE"
echo "Time: $(date)"
echo "----------------------------------------"
# Monitor log with statistics
tail -f "$LOG_FILE" | while read -r line; do
# Display the line
echo "$line"
# Count errors and warnings
if echo "$line" | grep -q "ERROR"; then
((ERROR_COUNT++))
echo ">>> ERROR COUNT: $ERROR_COUNT <<<"
# Alert on threshold
if [ $ERROR_COUNT -gt 10 ]; then
echo "!!! ALERT: More than 10 errors detected !!!"
# Could send notification here
fi
fi
if echo "$line" | grep -q "WARN"; then
((WARN_COUNT++))
echo ">>> WARN COUNT: $WARN_COUNT <<<"
fi
done
This comprehensive script demonstrates advanced tail usage:
Real-time log monitoring with tail -f
Live pattern matching and counting
Threshold-based alerting
Statistical analysis during monitoring
Can be extended with notifications (email, Slack, etc.)
# Monitor deployment logs
tail -F /var/log/deploy.log
# Watch for specific error patterns
tail -f app.log | grep -A 5 "Exception"
# Monitor multiple microservices
tail -f service1.log service2.log service3.log
# Track API response times
tail -f access.log | awk '{print $NF}' | grep -E "[0-9]+"
Practical Patterns and Idioms
Pattern 1: Show Recent Errors
# Last 50 error lines
grep ERROR application.log | tail -50
# Recent errors with context
grep -B 3 -A 3 ERROR application.log | tail -100
Pattern 2: Compare File Endings
# Compare last 10 lines of two files
diff <(tail file1.txt) <(tail file2.txt)
# Check if files end similarly
comm <(tail -100 log1.txt | sort) <(tail -100 log2.txt | sort)
Pattern 3: Extract Recent Time Period
# Last hour from timestamped log
tail -10000 app.log | grep "$(date -d '1 hour ago' '+%Y-%m-%d %H')"
# Last 1000 lines from today
tail -1000 app.log | grep "$(date '+%Y-%m-%d')"
Pattern 4: Continuous Processing Pipeline
# Real-time log → parse → analyze → alert
tail -f access.log | \
awk '{print $1, $7, $9}' | \
grep -E "GET|POST" | \
while read ip path status; do
if [ "$status" = "500" ]; then
echo "ALERT: 500 error from $ip on $path"
fi
done
tail vs. head Comparison
Feature
tail
head
Default Lines
Last 10
First 10
Follow Mode
✅ Yes (-f, -F)
❌ No
Skip Lines
tail -n +N (skip first N-1)
head -n -N (skip last N)
Primary Use
Recent data, log monitoring
File preview, headers
Performance Considerations
⚡ Performance Tips:
Large Files: tail is very efficient - it seeks to end of file rather than reading entire file
Follow Mode: Uses inotify on Linux for efficient file monitoring (low CPU usage)
Multiple Files: tail -f can monitor many files without significant overhead
Pipes: tail works efficiently in pipelines without loading entire input
🔍 Efficiency Example:
# Very fast even on huge file (1GB+)
tail -1000 huge_log_file.txt
# Efficient real-time monitoring
tail -f /var/log/syslog # Uses < 1% CPU
Common Pitfalls and Solutions
Pitfall 1: Grep Buffering in Pipes
⚠️ Problem: Output appears delayed when piping tail to grep
# Wrong: Keeps following old file after rotation
tail -f app.log # Stops working after logrotate!
# Correct: Use -F to handle rotation
tail -F app.log # Automatically follows new file
Pitfall 3: Following Doesn't Show Existing Content
💡 Remember:
# Shows last 10 lines, then follows
tail -f file.log
# Show more context before following
tail -n 100 -f file.log
# Show all existing content, then follow
tail -n +1 -f file.log
Advanced Techniques
Technique 1: Custom Update Interval
# Check file every 5 seconds instead of continuously
tail -f -s 5 app.log
# Useful for reducing CPU on very active logs
Technique 2: Tail from Remote System
# Monitor remote log via SSH
ssh user@server "tail -f /var/log/syslog"
# With compressed transfer
ssh user@server "tail -f /var/log/syslog" | gzip -c | gunzip
Technique 3: Tail with Timeout
# Follow for 60 seconds then exit
timeout 60 tail -f app.log
# Follow until pattern appears
tail -f app.log | grep -m 1 "Startup complete"