Articles / Linux

  • linux
  • tail
  • logrotate
  • inodes
  • sysadmin
  • debugging

Why tail -f Goes Silent After Log Rotation, and What -F Fixes

You leave tail -f /var/log/app.log running overnight, and in the morning it has stopped printing. The application is fine and the log is still being written. You are just watching the wrong file, and tail has no idea.

The fix is one capital letter. The reason it works is more interesting than the letter.

Reproduce it in thirty seconds

You do not need logrotate to see this. Make a directory and fake a rotation by hand.

cd "$(mktemp -d)"
echo one > app.log
tail -f app.log

In a second terminal, in the same directory, do what logrotate does:

mv app.log app.log.1
echo two > app.log
echo three >> app.log

The first terminal shows one and then nothing. "two" and "three" never appear. Stop it with Ctrl-C and run the same steps again with tail -F app.log, and it notices the swap, says it is following a new file, and prints both lines.

-f follows a file, not a name

When you run tail -f app.log, tail opens the path once and keeps that open file descriptor. The default for -f is to follow the descriptor, which is what --follow=descriptor spells out. The name is only used at the start.

A rename does not touch the inode. After mv app.log app.log.1, your descriptor still points at the same data, now reachable under a different name. Tail is faithfully following the file you asked for. It is simply no longer the one the application will write to next.

Quick detour: why the old file keeps growing

Hang on, this gets better. Many daemons hold their own descriptor open too. If the application never reopens its log, it keeps appending to app.log.1 after the rename, so tail is arguably right to stay put. That is why logrotate configs often send a SIGHUP, or run a post-rotate script, to make the daemon reopen its log by name.

The same mechanism explains why deleting a log does not free disk space while a process still holds it. Names and files are separate things on Linux, and most surprises in this area come from forgetting that.

What -F actually does

In GNU tail, -F is shorthand for --follow=name --retry. It does two things differently:

  • It watches the path, and if the path now refers to a different inode, it reopens it and reads the new file from the start.
  • With --retry, it keeps trying if the file is missing, which covers the gap between the rename and the new file being created.

Without the retry part, --follow=name on its own gives up when the file disappears. In the window where rotation has moved the old file and the daemon has not yet created the new one, -F reports that the file is inaccessible, waits, and then announces that it has appeared and carries on.

The copytruncate case behaves differently

Logrotate has another mode, copytruncate. It copies the log elsewhere and then truncates the original in place, so the inode never changes. This suits daemons that cannot reopen their logs.

Here plain tail -f copes: it notices the size dropped below its position, prints a "file truncated" message and carries on from the start. The catch is on the logrotate side. Lines written between the copy and the truncate are lost from both files, so tail cannot show you what was never kept.

When to use which

  • tail -F for any log that something else manages. This is nearly always what you want on a server.
  • tail -f for a file you want to stick with whatever happens to its name, such as watching a file you have just moved.
  • tail -F -n 0 if you only want new lines and not the last ten.

One more habit worth having: with several files, tail -F a.log b.log prints a header whenever the source changes, so you can tell which file a line came from.

Check it behaves on your system

Behaviour differs between implementations. GNU tail is what I have described; BSD and BusyBox versions have their own quirks around -F and retry. The quick test is the one at the top: rename, create, append, and see whether the new lines appear. It takes less time than reading the man page, and you will trust the result more.