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
On Debian or Ubuntu, install it with:
sudo apt update
sudo apt install logrotate
On Fedora or RHEL-compatible systems:
sudo dnf install logrotate
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
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
}
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:
-
dailychecks the log once a day; rotation happens only if it isn’t empty. -
rotate 14keeps 14 rotated files. With daily rotation, that’s roughly two weeks, but actual retention depends on when the file was last rotated. -
compressgzips older logs;delaycompressleaves the newest rotated file uncompressed until the next rotation. -
dateextgives rotated files a date suffix, which makes them easier to identify. -
create 0640 myapp admcreates a replacement file with the specified permissions and ownership. -
su myapp admruns 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. -
postrotateruns 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
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
--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
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
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
}
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
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)