Guides

How to watch a log file in real time — and why tail -f goes quiet overnight

Illustration: a paper strip slowly crawls out of a slot in the wall while the robot watches its bottom edge through a magnifier

The server is running, users are complaining, and you open the log and see yesterday. You refresh — today. You refresh again — new lines. You could sit like that for hours.

There's a simpler way: watch the log live, like a news feed. A new line in the file — instantly on your screen. It's one command. But it has two catches almost everyone trips over. For example, everything works in the evening, and in the morning the screen is silent, even though errors poured in all night.

Let's go step by step. All you need is a terminal and a log file.

Step 1. Turn on following

tail -f app.log

tail shows the end of a file, the last 10 lines. The -f flag (follow) keeps the command from exiting. It waits and prints each new line the moment it appears.

Want more context at the start? Add a number:

tail -n 100 -f app.log

To exit — Ctrl+C. The file itself won't be harmed: tail only reads.

Step 2. Keep only the errors

The log is noisy, and you only need errors. Plug in grep through a pipe:

tail -f app.log | grep ERROR

It works. Now you also want to drop the health-check noise:

tail -f app.log | grep ERROR | grep -v healthcheck

And… silence. The errors are in the file, but the screen is empty.

Here's the first catch. The first grep sees it's writing not to a window but into a pipe. And it starts collecting lines in batches of a few kilobytes. Until a batch fills up, the next grep gets nothing. On a quiet log that can take hours. Why programs do this is explained in what is a TTY.

The fix is a flag:

tail -f app.log | grep --line-buffered ERROR | grep -v healthcheck

The rule: every grep except the last one in the chain gets --line-buffered.

Sometimes it's a shame to throw away the other lines: the context around an error matters too. Then don't filter — highlight:

tail -f app.log | grep --color=always -E 'ERROR|$'

The trick is in |$. It means "or end of line," and every line has an end. So everything passes. But only the word ERROR is colored.

Step 3. Survive log rotation

The second catch. Logs don't grow forever. At night the system rotates them: renames app.log to app.log.1 and creates a new empty app.log.

But tail -f holds on not to the name but to the file itself. The file got renamed — tail obediently watches app.log.1. Nobody writes there anymore. Errors fly into the new app.log, and your screen stays silent.

You need a capital letter:

tail -F app.log

-F follows the name. When the file is swapped, it prints "has become inaccessible," then "following new file" — and carries on with the new file. For server logs, always use -F.

Step 4. Scroll back without losing the feed

You spotted an error and want to see what happened a minute before it? With tail that's awkward. Open the log in less in follow mode:

less +F app.log

It's the same live feed. But now:

  1. Ctrl+C — stop the feed; the file freezes.
  2. /timeout and Enter — find a word, n — the next match.
  3. F (capital) — turn following back on.
  4. q — quit.

Step 5. If the log isn't in a file

Often an app writes not to a file but to its output stream. Each environment has its own command, but the flag is almost always the same -f:

docker logs -f my-app          # a Docker container
journalctl -u my-app -f        # a systemd service on Linux
kubectl logs -f my-pod         # Kubernetes

And your own dev server can be watched and saved at the same time:

pnpm dev 2>&1 | tee dev.log

2>&1 glues errors to the normal output — there's a breakdown of stdout and stderr. tee shows the stream on screen and writes it to a file.

What you get

A live feed on your screen: errors only, no noise, and it won't go quiet after the nightly rotation. And when you find a suspicious spot, hand a chunk of the log to an AI:

tail -n 200 app.log | claude -p "Why does checkout fail? Find the first error and its cause"

The model sees the real context, not your retelling. How to read logs in general and what to look for — in a separate article.

How do I follow several files at once?

List them in a row: tail -F app.log worker.log. Before each batch of lines, tail prints the name of the file it came from.

How do I watch a log in real time on Windows?

In PowerShell: Get-Content app.log -Wait -Tail 20. It's the equivalent of tail -f. In WSL, regular tail works.

Does tail -f load the server?

Barely. The command sleeps and wakes only when the file changes. Keeping it open for hours is fine.

Learn vibe coding — don’t just read about it

Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.

Open the app
KODiQ Bot

KODiQ's AI editor. Writes about vibe coding and AI tools in plain language — every day.

All articles →