tail Command Examples

Display the End of Files

About tail

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:

💡 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:
  • tail -n +1 - Shows entire file (from line 1)
  • tail -n +5 - Skips first 4 lines
  • tail -n +100 - Shows from line 100 to end
  • Useful for skipping headers or known content

🎯 Common Use Case:

# Skip CSV header tail -n +2 data.csv | sort | head -10

Example 4: Display Last N Bytes

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
2024-11-13 10:15:23 - Log entry 2024-11-13 10:15:25 - Log entry 2024-11-13 10:15:27 - Log entry (continues updating in real-time...)
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!

Example 7: Monitor Multiple Files

tail -f access.log error.log
==> access.log <== 192.168.1.100 - - [13/Nov/2024:10:15:23] "GET /index.html HTTP/1.1" 200 192.168.1.101 - - [13/Nov/2024:10:15:24] "GET /style.css HTTP/1.1" 200 ==> error.log <== [13/Nov/2024:10:15:25] [error] Connection timeout to database [13/Nov/2024:10:15:26] [warn] Slow query detected
tail can monitor multiple files simultaneously:
  • Shows headers separating different files
  • Updates from all files appear in real-time
  • Great for correlating related logs
  • Use -q to suppress file headers
🎯 DevOps Tip: Monitor application and web server logs together to correlate errors with requests.

Example 8: Follow Until Process Ends

# Start a process python long_running_script.py & SCRIPT_PID=$! # Monitor its log until process completes tail -f --pid=$SCRIPT_PID script.log
The --pid option terminates tail when specified process dies:
  • Automatically stops following when process completes
  • Perfect for automated scripts and monitoring
  • No need to manually kill tail process
  • Useful in CI/CD pipelines

🤖 Automation Example:

#!/bin/bash # Start application ./myapp > app.log 2>&1 & APP_PID=$! # Monitor log until app exits tail -f --pid=$APP_PID app.log # App has finished, analyze logs grep ERROR app.log

Example 9: Combine with Grep for Filtered Monitoring

# Monitor only ERROR lines in real-time tail -f application.log | grep --line-buffered ERROR # Monitor multiple patterns tail -f app.log | grep --line-buffered -E "ERROR|WARN|CRITICAL" # Colored output tail -f app.log | grep --line-buffered --color=always ERROR
Combining tail with grep enables filtered real-time monitoring:
  • --line-buffered ensures immediate output (no buffering)
  • Filter logs for specific patterns in real-time
  • Reduce noise in busy log files
  • Add --color=always for highlighted matches
🎨 Enhanced Monitoring:
# Beautiful colored monitoring tail -f /var/log/syslog | grep -E --color=always 'error|fail|critical' # Count errors per minute tail -f app.log | grep ERROR | while read line; do echo "$(date '+%H:%M') $line" done

Example 10: Advanced Log Analysis Script

#!/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.)

Real-World Use Cases

Use Case 1: System Administration

# Monitor system log tail -f /var/log/syslog # Watch authentication attempts tail -f /var/log/auth.log | grep sshd # Monitor Apache access log tail -f /var/log/apache2/access.log # Track kernel messages tail -f /var/log/kern.log # Watch all logs simultaneously tail -f /var/log/{syslog,auth.log,kern.log}

Use Case 2: Development and Debugging

# Monitor application during development tail -f app.log | grep --color DEBUG # Watch database query log tail -f /var/log/mysql/query.log # Monitor Docker container logs docker logs -f container_name 2>&1 | tail -100 # Track build output tail -f build.log | grep -E "ERROR|WARNING"

Use Case 3: DevOps and Monitoring

# 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:
🔍 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
# Problem: grep buffers output tail -f app.log | grep ERROR # Appears slow! # Solution: Use --line-buffered tail -f app.log | grep --line-buffered ERROR # Immediate output!

Pitfall 2: Log Rotation Issues

⚠️ Problem: Using -f when logs are rotated
# 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"

Related Commands

Quick Reference

Most Common tail Commands

# Last 10 lines tail file.txt # Last 20 lines tail -n 20 file.txt # Last 100 bytes tail -c 100 file.txt # Follow file in real-time tail -f /var/log/syslog # Follow with rotation support tail -F app.log # Skip first 5 lines, show rest tail -n +6 file.txt # Monitor multiple files tail -f file1.log file2.log # Follow until process ends tail -f --pid=1234 app.log # Show last 50, then follow tail -n 50 -f app.log # Filtered real-time monitoring tail -f app.log | grep --line-buffered ERROR