How to Monitor Real-Time Logs in Linux: tail, journalctl, multitail

Monitor real-time logs in Linux using tail -f, journalctl -f, and multitail — follow multiple log files simultaneously, filter live output, and build production log monitoring workflows.

April 22, 2026·6 min read·Damon

Watching logs in real time is how you catch errors as they happen — during deployments, under load tests, or when chasing an intermittent bug. Here's every way to do it.


TL;DR

tail -f /var/log/nginx/error.log                    # follow a flat file
journalctl -fu nginx                                # follow systemd service logs
journalctl -f -p err                                # all services, errors only
tail -f /var/log/nginx/error.log | grep ERROR       # follow + filter
multitail /var/log/nginx/error.log /var/log/app.log # multiple files, split view

tail -f: The Standard Tool

tail -f /var/log/nginx/error.log

-f follows the file as it grows. Output stops when the file stops changing.

# Follow + filter (only show ERROR lines)
tail -f /var/log/app/app.log | grep "ERROR"

# Follow with color highlighting
tail -f /var/log/nginx/error.log | grep --color=always -E "error|warn|$"

# Follow last 100 lines, then stream
tail -n 100 -f /var/log/app/app.log

# Follow multiple flat files (alternates between them)
tail -f /var/log/nginx/access.log /var/log/nginx/error.log

journalctl -f: For systemd Services

journalctl -f is the equivalent of tail -f for services managed by systemd:

# Follow a specific service
journalctl -fu nginx

# Follow + filter by priority (errors and above)
journalctl -fu nginx -p err

# Follow multiple services
journalctl -f -u nginx -u php-fpm

# All services, errors only
journalctl -f -p err

# Follow + grep
journalctl -fu myapp | grep -i "exception\|fatal\|crash"

The -u flag (unit) targets a specific service. Without it, you see all system logs.


Real-Time Filtering Techniques

grep with color

# Highlight errors in red while showing everything
tail -f /var/log/nginx/error.log | grep --color=always -iE "error|crit|alert|$"

# Show only 502 and 504 in access log
tail -f /var/log/nginx/access.log | grep -E " 50[24] "

awk for structured parsing

# Show only lines where response time > 1 second (if logged as last field)
tail -f /var/log/nginx/access.log | awk '$NF > 1.0 {print}'

# Show 5xx errors with timestamp and IP
tail -f /var/log/nginx/access.log | awk '$9 >= 500 {print $1, $7, $9}'

Watch for specific patterns with alert

# Alert when error rate spikes
tail -f /var/log/app/app.log | awk '
  /ERROR/ {count++}
  count > 10 {
    print "ALERT: " count " errors in last lines"
    count = 0
  }
'

multitail: Multiple Logs in Split View

multitail splits the terminal and shows multiple log files simultaneously:

# Install
apt install multitail    # Ubuntu
dnf install multitail    # RHEL

# Two files side by side
multitail /var/log/nginx/error.log /var/log/app/app.log

# Three files
multitail /var/log/nginx/error.log /var/log/nginx/access.log /var/log/app/app.log

# With color schemes
multitail -ci green /var/log/nginx/access.log -ci red /var/log/nginx/error.log

# Follow journald output alongside a file
multitail -j /var/log/app/app.log

Navigate with arrow keys. Press q to quit.


Real Examples

Monitor a deployment

# Watch application log while deploy runs
tail -f /var/log/app/app.log &
LOG_PID=$!

# Run deployment
./deploy.sh

# Stop following when done
kill $LOG_PID

Watch nginx 502 errors in real time

# Tail error log, show only upstream errors
tail -f /var/log/nginx/error.log | grep -i "upstream\|502\|connect"

Monitor for OOM kills in real time

# Follow kernel log for OOM events
journalctl -f -k | grep -i "oom\|killed"

Watch all service errors simultaneously

journalctl -f -p err --no-hostname

Live response code breakdown

# Count response codes every 5 seconds from nginx access log
tail -f /var/log/nginx/access.log | awk '
{codes[$9]++; count++}
count % 100 == 0 {
  print "--- Last 100 requests ---"
  for (c in codes) print c":", codes[c]
  delete codes
}'

Follow Logs That Rotate

Standard tail -f loses the file handle when a log is rotated (the file gets renamed and a new one created). Use tail -F (capital F):

# -F follows by filename, not file descriptor
# Works across log rotation
tail -F /var/log/nginx/error.log

journalctl -f handles rotation automatically since it reads from the journal, not a file.


Common Mistakes

Mistake 1: Using tail -f on a log that gets rotated Use tail -F (capital F) instead. -f follows the file descriptor; -F follows the filename and reopens when the file changes.

Mistake 2: Not using --no-pager with journalctl in scripts journalctl sends output through less by default. In scripts, add --no-pager. For -f mode this doesn't matter, but when piping to grep it does:

journalctl -u nginx --no-pager | grep ERROR

Mistake 3: Missing logs because buffer is full When piping tail -f through multiple filters, the pipe buffer can cause delayed output. Add stdbuf -oL to disable buffering:

tail -f /var/log/app.log | stdbuf -oL grep "ERROR" | stdbuf -oL awk '{print $0}'

Mistake 4: Following a log that grows too fast On a busy server, tail -f on an access log can flood your terminal. Filter first:

tail -f /var/log/nginx/access.log | grep " 5[0-9][0-9] "
# Only show 5xx errors, not every request

Pro Tips

# Follow log and timestamp each line as it arrives
tail -f /var/log/app.log | ts '[%Y-%m-%d %H:%M:%.S]'
# (requires 'ts' from moreutils package)

# Follow with context — show N lines before/after a match
tail -f /var/log/app.log | grep -A 3 "ERROR"

# Save real-time output to file AND show on screen
tail -f /var/log/app.log | tee /tmp/incident_$(date +%Y%m%d_%H%M%S).log

# Combine systemd and file log in one stream
{ journalctl -fu nginx & tail -f /var/log/app/app.log; } | grep -iE "error|warn"

# Alert on pattern match with sound
tail -f /var/log/nginx/error.log | grep --line-buffered "CRIT" | \
  while read line; do echo "$line"; echo -e '\007'; done

Conclusion

tail -F (capital F) for flat files — it handles log rotation. journalctl -f -u <service> for systemd services. Filter with grep --color=always -E "pattern|$" to highlight matches while keeping all output. For watching multiple services during a deployment or incident, journalctl -f -p err gives you a filtered view across everything at once.


Related: Linux Log Analysis: Debug Issues Like a Senior Engineer — the full log investigation workflow beyond just watching. journalctl Filter by Time Range — go back in time to investigate past events.