How to Tail and Filter Logs in Real Time on Linux

By 

Published on

6 min read

Terminal filtering a live stream of Linux log entries

When you reproduce a bug or restart a service, the most useful view is often the log scrolling live as it happens. You want to see each new line when it is written, but you may also need to hide routine entries so the warning or error that matters does not disappear in the noise.

Linux provides several ways to follow logs. Use tail -F for a plain log file, less +F when you need to pause and search, and journalctl -f for output stored in the systemd journal. This guide shows how to use each tool and filter the live stream.

Quick Reference

For printable quick references, see the tail , grep , less , and journalctl cheatsheets.

TaskCommand
Follow a filetail -f /var/log/app.log
Follow and survive rotationtail -F /var/log/app.log
Follow only newly appended linestail -n 0 -F /var/log/app.log
Show last N lines, then followtail -n 100 -f /var/log/app.log
Follow several files at oncetail -F /var/log/a.log /var/log/b.log
Follow, scroll, search, and filterless +F /var/log/app.log
Follow a systemd unitjournalctl -f -u nginx
Follow errors and more severe entriesjournalctl -f -p err
Filter file logs by texttail -F app.log | grep -i error
Filter journal messages by textjournalctl -f -u nginx -g 'timeout|failed'

Follow a File with tail -f

The tail command prints the end of a file, and the -f (--follow) option keeps reading as new data is appended. This is the quickest way to watch a plain-text log:

Terminal
tail -f /var/log/nginx/access.log

The terminal shows the last 10 lines and then waits, adding each new request as it arrives. Press Ctrl+C to stop. To start with more context, specify the number of existing lines to show:

Terminal
tail -n 100 -f /var/log/nginx/access.log

If you want to ignore existing entries and display only lines appended after the command starts, set the initial line count to zero:

Terminal
tail -n 0 -f /var/log/nginx/access.log

One catch is log rotation. Plain -f follows the open file descriptor, so it can keep watching the old file after that file is renamed. On GNU tail, -F is equivalent to --follow=name --retry: it watches the path and keeps trying to reopen the file when it is replaced or temporarily unavailable.

Terminal
tail -F /var/log/nginx/access.log

You can also watch more than one file in the same session. Pass several paths, and tail prints a ==> path <== header each time the output switches to a different file:

Terminal
tail -F /var/log/nginx/access.log /var/log/nginx/error.log

Those headers tell you which file produced the lines that follow, which matters when two logs use a similar format.

Use -F for a long-running session on a rotating log. The tail command guide covers line counts, byte offsets, and other follow options.

Filter a Live Stream with grep

Pipe the followed output into grep to keep only matching lines. The following command ignores case, so it matches error, ERROR, and other capitalization variants:

Terminal
tail -F /var/log/app.log | grep -i error

In this two-command pipeline, grep writes directly to the terminal and normally displays each match immediately. If you send its output into another command, GNU grep switches to full buffering. Add --line-buffered before the next pipeline stage so matches continue moving one line at a time:

Terminal
tail -F /var/log/app.log | grep --line-buffered -i error | awk '{ print $1, $2, $NF }'

Here, grep flushes each match to awk, which prints the first two and last whitespace-separated fields. A later command can still have its own buffering rules, so check each stage if output remains delayed.

Use extended regular expressions to match several severity words in one pass:

Terminal
tail -F /var/log/app.log | grep -Ei 'error|warning|critical'

To hide a noisy health-check endpoint while keeping all other requests, invert the match with -v:

Terminal
tail -F /var/log/nginx/access.log | grep -v '/health'

The grep command guide covers fixed strings, regular expressions, and inverted matches in more detail.

Scroll and Search with less +F

tail -f shows new lines but does not let you inspect earlier entries without stopping the command. The less pager has its own follow mode and lets you switch between live output and normal navigation:

Terminal
less +F /var/log/app.log

Press Ctrl+C to pause following. You can then scroll with the arrow keys or search forward by typing /pattern and pressing Enter.

To hide nonmatching lines, type &pattern and press Enter. Enter & followed by Enter to clear the filter. Press uppercase F to return to follow mode; any active filter remains in effect while new lines arrive. The less command guide covers navigation, searches, and display options.

Follow a Service with journalctl -f

On a systemd system, service output captured by systemd-journald is read with journalctl. Use -f to follow new journal entries and -u to limit them to one unit:

Terminal
journalctl -f -u nginx

This follows entries associated with the nginx unit, including service lifecycle messages and output sent to the journal. Applications can also write dedicated files. If Nginx access requests are stored in /var/log/nginx/access.log, follow that file with tail -F instead.

Because journal entries contain structured fields, you can filter by priority. A single priority includes that level and all more severe levels, so err shows err, crit, alert, and emerg entries:

Terminal
journalctl -f -u nginx -p err

Use -g (--grep) to match a regular expression against the MESSAGE field while following:

Terminal
journalctl -f -u nginx -g 'timeout|failed'

To follow warnings and more severe entries from the current boot across all accessible units, combine -f, -p, and -b:

Terminal
journalctl -f -b -p warning

The journalctl command guide covers time ranges, boot selection, unit filters, and journal fields.

Which Tool to Use

The log destination determines the first choice. Use tail -F for a rotating plain-text file, then pipe it through grep when you need text filtering. Use less +F when you expect to pause, scroll backward, search, or interactively hide nonmatching lines. Use journalctl -f when the messages are stored in the systemd journal and you want to filter by unit, priority, boot, or message text.

Troubleshooting

Permission denied when opening a log
Check the file permissions with ls -l /path/to/log. Run sudo tail -F /path/to/log only if your account is authorized to read that log. For the system journal, administrators can use sudo journalctl, while many distributions also grant journal access through groups such as adm or systemd-journal.

No new lines appear
Confirm that the application is still appending to the path you opened. If the file was rotated or recreated, restart with tail -F. Also remember that tail follows appended data; it does not report text rewritten in place earlier in the file.

journalctl -p err misses a message containing ERROR
The -p option checks the structured PRIORITY field, not words inside the message. If an application logs the word ERROR without assigning an error priority, use a text filter such as journalctl -f -u SERVICE -g 'error'.

Conclusion

Start with the unfiltered stream to confirm that you have the correct source, then add one filter at a time so you do not hide the event you are trying to diagnose. When a filter proves useful more than once, save it as a shell alias or a short script so the next incident starts from a view you already trust.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page