Application logs can grow until they fill a VPS disk, but deleting a large log file by hand is not always a fix. A running process may keep writing to the file it already has open—even after you remove its directory entry. The safer approach is to configure log rotation and tell the application how to reopen its logs.
This guide sets up logrotate for a custom application that writes to /var/log/myapp/app.log. The example assumes the application runs as the myapp user and can reopen its log when it receives SIGUSR1. Check your application’s documentation before choosing a signal; not every program handles it the same way.
Check where the application writes logs
First, confirm the path and ownership of the log file:
sudo ls -l /var/log/myapp/
sudo stat /var/log/myapp/app.log
If you are unsure whether the application still has a file open, inspect its file descriptors. Find its PID, then check the process’s open files:
pgrep -a myapp
sudo lsof -p PID | grep '/var/log/myapp/'
Replace PID with the process ID. If lsof is not installed, /proc/PID/fd can also show the process’s open file descriptors, though the output is less convenient to interpret.
Deleting an active log is risky: the process can continue writing to the unlinked file, while du no longer counts it by name. If you are diagnosing a disk-space discrepancy, compare filesystem usage with directory usage and inspect open deleted files; the guide to finding open file handles after deleting a large file explains that diagnostic path.
Write a per-application logrotate rule
Create a file under /etc/logrotate.d/:
sudoedit /etc/logrotate.d/myapp
Add a rule such as:
/var/log/myapp/app.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 myapp adm
sharedscripts
postrotate
/bin/kill -USR1 $(cat /run/myapp.pid) 2>/dev/null || true
endscript
}
Adjust the path, owner, group, permissions, and signal for your application. The PID-file command is only an example: use a reliable PID source, such as the service’s documented PID file, and avoid signaling an unrelated or stale process.
Here is what the main directives do:
-
dailychecks the log for rotation once per day when logrotate runs. It does not create a timer itself. -
rotate 14keeps up to 14 rotated files. -
compresscompresses older rotations;delaycompresswaits until the next rotation before compressing the newest rotated file. -
missingokavoids an error if the log does not exist. -
notifemptyskips empty files. -
create 0640 myapp admcreates a new active log with the specified mode, owner, and group after rotation. -
postrotateruns a command after rotation. In this example, it asks the application to reopen its log. -
sharedscriptsruns the post-rotation script once for this stanza, rather than once per matching log file.
Logrotate normally renames the active file and creates a replacement. The application must then close its old file handle and open the new path. If it does not, it may continue writing to the rotated file. Some applications support a reload signal; others require a service reload, a documented control command, or a different logging setup.
If the application cannot reopen logs, copytruncate is an alternative:
copytruncate
It copies the current log to a rotated file and truncates the original in place, so the application can keep its file handle. However, log lines written during the copy-and-truncate interval can be lost. Prefer a supported reopen or reload mechanism when possible.
Test the configuration before forcing rotation
Logrotate can test a configuration without changing files:
sudo logrotate --debug /etc/logrotate.d/myapp
Debug mode reports what logrotate would do, but does not rotate the log or update its state. Read the output for parsing errors, unexpected paths, and skipped files.
To request a rotation immediately, use the force option only after reviewing the rule and confirming you have enough disk space:
sudo logrotate --force /etc/logrotate.d/myapp
A forced run ignores normal rotation conditions, so it is useful for a controlled test but not something to put into routine automation. Check the resulting files and the application’s status afterward:
sudo ls -lh /var/log/myapp/
sudo systemctl status myapp --no-pager
For service diagnosis, reading systemctl status output can help distinguish an application failure from a rotation problem. If the application logs to the systemd journal instead of a file, inspect its service logs with journalctl rather than adding an unnecessary file-based rotation rule.
Confirm that rotation will run
On many systemd-based Linux distributions, a timer invokes logrotate. Check whether it is scheduled and when it last ran:
systemctl status logrotate.timer --no-pager
systemctl list-timers logrotate.timer
The timer may not exist on every distribution or installation. Some systems use cron instead. Check the local setup rather than assuming that writing a file under /etc/logrotate.d/ automatically runs it.
Logrotate also tracks when files were last rotated in a state file, commonly /var/lib/logrotate/status. Avoid deleting or editing that file to “fix” a rule without understanding the effect: logrotate may treat logs as due for rotation again.
Common mistakes to avoid
Rotating a file the application does not use
Applications can log to the journal, a container’s standard output, or a different path than expected. Verify the actual destination before creating a rule.
Choosing the wrong owner or mode
If the replacement log is owned by root and the application runs as myapp, it may fail to write after rotation. Match create to the application’s runtime user and the access policy for log readers.
Assuming a signal is universal
SIGUSR1 is not a standard “reopen logs” instruction for every program. A wrong signal can do nothing or trigger unrelated behavior. Confirm the supported mechanism, then test it outside a critical period.
Forgetting rotated logs still consume space
Compression reduces the size of older text logs, but retention still matters. Estimate how quickly the application generates logs and choose a retention period that fits both operational needs and available storage.
A good rotation rule is specific to the application: it names the real log path, creates a writable replacement, and uses a verified reopen mechanism. Test the configuration first, then confirm that the service continues logging to the new file.
I'm building SSHFlow — an SSH client that organizes terminals, SFTP, code editing, and server tools into workspaces.
Top comments (0)