logrotate: automatic log rotation and archiving
Application logs fill up disk space within a week, and manually running rm *.log is a recipe for trouble. logrotate handles this automatically: it rotates, compresses, and deletes old files on a schedule. Let’s see how it works and how to set it up in five minutes.
How It Works
logrotate runs daily through cron. The default config lives in /etc/logrotate.conf, and additional configs are included from /etc/logrotate.d/. During rotation, the current file gets renamed, a new empty one is created, old copies are compressed and numbered.
The cycle looks like this:
The mechanism relies on rename or mv, so the process must hold the file descriptor open. If rotation isn’t picked up by the application, you end up with duplication or an empty log.
Configuration Structure
Files from /etc/logrotate.d/ override global values for specific logs. The format is straightforward:
Directives inherit from the global config unless overridden. You can specify multiple paths separated by spaces or use a glob pattern — convenient for rotating all application logs in one block.
Key Directives
Basic parameters covering 90% of use cases:
| Directive | Purpose | Example |
|---|---|---|
rotate N | number of copies to keep | rotate 7 |
size N | size threshold to trigger rotation | size 100M |
missingok | not an error if file is missing | — |
notifempty | skip empty logs | — |
compress | compress old logs (default gzip) | — |
dateext | use date instead of number in name | — |
dateformat | date format | dateformat -%Y%m%d |
postrotate ... endscript | commands after rotation | reload service |
prerotate ... endscript | commands before rotation | prepare directories |
size overrides weekly/monthly/daily when set. Rotation happens when the file reaches the specified size AND the interval has passed. So size 100M with weekly means rotation no earlier than a week and only if the file exceeds 100M.
dateext is incompatible with long filenames on some filesystems. If the log name plus date suffix exceeds 255 bytes — logrotate will fail.
Example Config for an Application
Assume your myapp service writes to /var/log/myapp/. Config:
sharedscripts ensures postrotate runs once for all rotated files, not once per file. Without it, the script executes as many times as files match the rotation criteria.
For Python applications using standard library rotation:
su changes the rotation process owner — useful when the application runs under a separate user with restricted log permissions.
Debugging and Manual Execution
Dry-run mode shows what would happen without making changes:
Output contains each decision: which file gets renamed, which gets compressed, which commands run. Look for renaming and running postrotate script lines.
Force rotation bypassing the schedule:
-f ignores the last rotation time and size conditions. Combining with -d is a safe way to verify before production:
To rotate a specific log outside the schedule but respecting conditions — use the state file:
Syntax check without execution:
If there are no errors — output is empty (without -d) or shows the action plan (with -d).
Do not edit /var/lib/logrotate/status manually in production without understanding the format. One mistake — and logrotate decides rotation already happened, skipping all files until the next cron run.
Default cron setup:
On most distros you don’t need to touch this file. If you need rotation more often than once a day — add to /etc/cron.hourly/ or write a separate cron job.