DEV Community

Big Mazzy
Big Mazzy

Posted on Originally published at serverrental.store

How to Rotate Logs on a Linux Server Without Losing Data

A disk alert fired at 2 a.m. because one application log had grown to 38 GB—and the service kept writing to it after the file was renamed. Renaming a log is not the same as making a process start a new one. Here’s how to set up log rotation, check that your application reopens its logs, and avoid the common traps that can cost you data.

What log rotation does (and doesn’t do)

Log rotation typically renames a full log, creates a fresh file at the original path, and eventually compresses or removes older files. On most Linux distributions, logrotate handles this work.

But rotation alone doesn’t tell an application to stop writing to the old file. A process usually keeps an open file descriptor, which points to the original file even after it’s renamed. The result: the new log stays empty while the renamed file keeps growing.

The safe approach is to rotate the file and tell the application to reopen its logs—or use copytruncate as a fallback when the application cannot do that.

Check what’s already installed

Before adding a configuration, check whether logrotate is present and how it’s scheduled:

logrotate --version
systemctl list-timers | grep -i logrotate
Enter fullscreen mode Exit fullscreen mode

On Debian or Ubuntu, install it with:

sudo apt update
sudo apt install logrotate
Enter fullscreen mode Exit fullscreen mode

On Fedora or RHEL-compatible systems:

sudo dnf install logrotate
Enter fullscreen mode Exit fullscreen mode

Many systems already include a daily timer or cron job. Avoid adding a second schedule without checking first; two rotation runs can make troubleshooting confusing.

Configure a log that the application can reopen

Suppose an application writes to /var/log/myapp/app.log, runs as myapp, and has a systemd unit called myapp.service. Create a dedicated config file:

sudo nano /etc/logrotate.d/myapp
Enter fullscreen mode Exit fullscreen mode

Add:

/var/log/myapp/app.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    dateext
    create 0640 myapp adm
    su myapp adm

    postrotate
        /usr/bin/systemctl kill --signal=HUP --kill-whom=main myapp.service
    endscript
}
Enter fullscreen mode Exit fullscreen mode

Adjust the path, user, group, and unit name for your setup. The myapp process must handle SIGHUP by closing and reopening its log file. Check its documentation before relying on that behavior. If it doesn’t support reopening logs, use the fallback below.

Here’s what the directives do:

  • daily checks the log once a day; rotation happens only if it isn’t empty.
  • rotate 14 keeps 14 rotated files. With daily rotation, that’s roughly two weeks, but actual retention depends on when the file was last rotated.
  • compress gzips older logs; delaycompress leaves the newest rotated file uncompressed until the next rotation.
  • dateext gives rotated files a date suffix, which makes them easier to identify.
  • create 0640 myapp adm creates a replacement file with the specified permissions and ownership.
  • su myapp adm runs file operations as that user and group. This is useful for logs in directories owned by an application account. Check that the logrotate version and permissions on your system support this arrangement.
  • postrotate runs the command that asks the service to reopen its log.

A practical tip: test the signal handling before trusting the schedule. Check that the application logs to the newly created app.log after a manual rotation. A successful systemctl command only proves the signal was sent; it doesn’t prove the application acted on it.

Test without forcing a rotation

First, check the config for errors without changing files:

sudo logrotate --debug /etc/logrotate.d/myapp
Enter fullscreen mode Exit fullscreen mode

Debug mode doesn’t rotate logs or update the state file. To test the real rotation, back up a non-production log or use a test service, then run:

sudo logrotate --verbose --force /etc/logrotate.d/myapp
Enter fullscreen mode Exit fullscreen mode

--force rotates regardless of the schedule, so don’t use it casually on production logs. It can also make the next scheduled run behave differently because logrotate tracks when files were last rotated.

After a test, inspect the files and ownership:

sudo ls -l /var/log/myapp/
sudo tail -n 20 /var/log/myapp/app.log
Enter fullscreen mode Exit fullscreen mode

Generate a line of application activity and confirm it appears in the new app.log, not just in a rotated file. Then check the service:

sudo systemctl status myapp.service
Enter fullscreen mode Exit fullscreen mode

When the application cannot reopen its log

If the application has no supported reopen mechanism, copytruncate may be the only practical option:

/var/log/myapp/app.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    copytruncate
    su myapp adm
}
Enter fullscreen mode Exit fullscreen mode

With copytruncate, logrotate copies the current file and then truncates the original in place. The application continues writing through its existing file descriptor.

There’s a trade-off: a small amount of log data can be lost if the application writes between the copy and the truncate. For high-volume or audit-critical logs, prefer a supported reopen signal or another logging setup that streams to syslog or journald. Don’t treat copytruncate as perfectly lossless.

Set retention based on disk, not habit

Fourteen daily files can be reasonable for a small service, but log volume matters more than the number of files. If an app writes 500 MB a day, two weeks of uncompressed logs can use several gigabytes. Compression helps, but the savings depend on the log contents.

Check actual usage before choosing a retention period:

sudo du -sh /var/log/myapp
sudo du -h /var/log/myapp | sort -h | tail
Enter fullscreen mode Exit fullscreen mode

Also check whether your application already performs its own rotation. Two independent rotation mechanisms acting on the same file can cause missing logs or unexpected filenames.

Another tip from practice: monitor free disk space separately from log rotation. Rotation can fail because of a full filesystem—the very situation it’s meant to help with. Alert before the disk is nearly full, and consider whether logs should live on a separate filesystem on busy servers.

If you’re choosing a server

For a standard Linux VM that runs an application and its logs, PowerVPS is one option to evaluate. For GPU-heavy workloads, Vast.ai offers GPU rental; compare availability, storage, and pricing for the specific workload before committing. Neither changes the rotation basics: size retention for the disk you have, and make sure the application can reopen its logs.

The Server Rental Guide is also a useful resource when comparing hosting options.

Summary

A reliable rotation setup needs more than a schedule: configure retention and permissions, then make sure the application reopens its log after rotation. Test with --debug first, and use --force only when you’re prepared for an actual rotation. When reopen signals aren’t supported, copytruncate is a workable fallback—but it has a small data-loss window. Finally, monitor disk space; logrotate is useful, not a substitute for an alert.

Top comments (0)