logrotate
Overview
logrotate rotates, compresses, and retires log files so they do not fill disks. On Ubuntu it is driven by a systemd timer or cron, reading /etc/logrotate.conf plus drop-ins in /etc/logrotate.d/. Application logs you add should get a file under /etc/logrotate.d/. Journald logs are not managed here — use journalctl --vacuum-* for the journal.
Syntax
logrotate [options] configfile
sudo logrotate -d /etc/logrotate.conf
sudo logrotate -f /etc/logrotate.d/rsyslogCommon Options
| Option | Description |
|---|---|
-d |
Debug/dry-run — no changes |
-f |
Force rotation even if not due |
-v |
Verbose |
-s statefile |
Alternate state file (default /var/lib/logrotate/status) |
--skip-state-cleanup |
Keep status entries for vanished logs (version-dependent) |
Common config directives
| Directive | Meaning |
|---|---|
daily / weekly / monthly / hourly |
Time-based rotation |
size 100M / maxsize 100M |
Size-based (see man for size vs maxsize) |
rotate N |
Keep N old logs |
compress / delaycompress |
gzip (delay: skip most recent rotated) |
missingok |
Don’t error if log absent |
notifempty |
Skip empty logs |
create mode owner group |
Create new empty log after rotate |
copytruncate |
Copy then truncate in place (apps that never reopen) |
dateext / dateformat |
Date-based suffixes |
sharedscripts |
Run postrotate once for the whole block |
postrotate … endscript |
Reload/signal app after rotate |
su user group |
Run as user when directories are restricted |
olddir |
Move rotated files elsewhere |
maxage days |
Remove rotated logs older than N days |
Key Use Cases
- Keep
/var/logfrom filling root - Rotate custom application logs with reload hooks
- Force rotation during an incident when a log explodes
- Dry-run config after edits before production force
Examples with Explanations
Dry-run entire system config
sudo logrotate -d /etc/logrotate.confShows which logs would rotate and why (or why not). No files changed. Always do this after editing drop-ins.
Force one drop-in (verbose)
sudo logrotate -f -v /etc/logrotate.d/rsyslog
# or your app:
sudo logrotate -f -v /etc/logrotate.d/myappUse when testing a new stanza or recovering from a multi-GB log that should have rotated.
Inspect state
sudo cat /var/lib/logrotate/status | head -50
sudo grep myapp /var/lib/logrotate/statusState tracks last rotation times; corrupted/stale state can skip or confuse schedules — know where it lives.
Example application drop-in
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
create 0640 myapp myapp
sharedscripts
postrotate
systemctl reload myapp >/dev/null 2>&1 || true
endscript
}After install:
sudo logrotate -d /etc/logrotate.d/myapp
sudo logrotate -f -v /etc/logrotate.d/myapp
ls -la /var/log/myapp/copytruncate when the app won’t reopen
/var/log/legacy/app.log {
size 100M
rotate 7
copytruncate
missingok
compress
delaycompress
}copytruncate avoids needing a signal, but can race and drop a few lines. Prefer apps that reopen on SIGHUP/systemctl reload with create + postrotate.
size-based emergency pattern
/var/log/myapp/debug.log {
size 500M
rotate 5
compress
missingok
notifempty
copytruncate
}Helps when a debug flag left on would otherwise fill the disk overnight.
When does it run? (Ubuntu)
systemctl list-timers | grep -i logrotate
systemctl status logrotate.timer logrotate.service
# classic cron path may still exist on some releases:
ls /etc/cron.daily/logrotateTimers can delay runs if the machine was off (Persistent= semantics vary).
Disk pressure triage with logs
df -h /var/log
sudo du -xh /var/log | sort -h | tail
sudo logrotate -f -v /etc/logrotate.conf
# journal is separate:
journalctl --disk-usage
sudo journalctl --vacuum-size=500MUnderstanding Output
-d / -v lines explain decisions: “log does not need rotating”, “log needs rotating”, compression steps, and postrotate execution. Failures often come from permissions (su needed), missing directories, or postrotate scripts exiting non-zero.
Exit code non-zero should be treated as config or script failure — check unit logs:
journalctl -u logrotate.service -n 50Notes & Pitfalls
- Journald ≠ logrotate — vacuum the journal separately.
- Prefer reload/reopen over
copytruncatewhen the app supports it. - After rotate, confirm the app still writes to the live path (not a deleted inode).
sharedscripts+ wildcards: postrotate runs once; without it, once per file.- Permissions: log dirs owned by apps may need
suin the stanza. - Compressing huge logs can spike CPU/disk —
delaycompressspreads pain. - Don’t rotate active database files or non-log data with logrotate recipes.
- Test with
-din CI or staging before shipping drop-ins.
Additional Resources
man logrotateman logrotate.conf/etc/logrotate.confand/etc/logrotate.d/*on the host