The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Debug a configuration | sudo logrotate --debug /etc/logrotate.conf | View examples |
| Run verbosely | sudo logrotate --verbose /etc/logrotate.conf | View examples |
| Test with isolated state | sudo logrotate --state /run/app-logrotate.state \
--verbose /etc/logrotate.d/app | View examples |
| Force a rotation | sudo logrotate --force /etc/logrotate.d/app | View examples |
| Rotate by size | size 100M | View examples |
| Cap between intervals | maxsize 500M | View examples |
| Keep archive generations | rotate 14 | View examples |
| Expire old archives | maxage 90 | View examples |
| Use sortable date suffixes | dateext | View examples |
| Compress archives | compress | View examples |
| Delay compression | delaycompress | View examples |
| Create replacement securely | create 0640 app adm | View examples |
| Run scripts once | sharedscripts | View examples |
| Signal the writer | postrotate | View examples |
| Copy then truncate in place | copytruncate | View examples |
| Drop rotation identity | su app adm | View examples |
| Inspect rotation scheduling | systemctl status logrotate.timer logrotate.service \
--no-pager | View examples |
Log rotation is a data-lifecycle operation, not just a disk-space setting. Align retention with legal, security, backup, and incident-response requirements; confirm the writer can reopen its file; and dry-run every policy. logrotate may run as root and execute scripts, so configuration ownership and writable parent directories are security boundaries. Scheduling, state paths, available directives, and default include locations vary by distribution and logrotate release.
Step by step
Detailed examples
Dry-run first and understand state-file effects
--debug is the safe parser and decision preview: it does not rotate or update state. A normal verbose run changes files and state; --force can also remove the oldest retained archive. logrotate locks its state file to prevent concurrent runs. Test a copied fixture tree where possible, then inspect the scheduler and production state rather than repeatedly forcing live data.
sudo logrotate --debug /etc/logrotate.conf
systemctl status logrotate.timer --no-pager
systemctl list-timers logrotate.timer --all
sudo sed -n '1,80p' /var/lib/logrotate/status Translate policy into both time and storage bounds
daily or weekly controls eligibility only when logrotate itself runs frequently enough. rotate bounds generations; maxage applies when rotation is processed and is not a standalone cleanup daemon. size replaces the time criterion, while maxsize allows early rotation alongside it. Forecast peak volume and compression delay so a full filesystem does not arrive before the next scheduler run. Deletion must agree with backup and compliance holds.
/var/log/app/app.log {
daily
maxsize 500M
rotate 30
maxage 90
dateext
missingok
notifempty
} Compress only after the writer releases the archive
compress saves space but can surprise programs that keep writing to the renamed file. delaycompress leaves the newest rotated file plain until the next cycle, giving a successfully signaled writer time to reopen. Compression consumes CPU and temporary disk space; verify headroom and downstream shipper support. Encrypt or tightly restrict archives containing sensitive records because compression is not protection.
/var/log/app/app.log {
daily
rotate 30
compress
delaycompress
dateext
} Rename, recreate, and signal a cooperative writer
The preferred flow renames the active file, creates a correctly owned replacement, and signals the application to reopen. Confirm the application's documented signal or reload command; a wrong signal can terminate it. sharedscripts prevents multiple signals for wildcard paths, but postrotate runs only when rotation occurs. Use absolute commands and avoid interpreting attacker-controlled filenames in privileged scripts.
/var/log/app/*.log {
daily
rotate 14
compress
delaycompress
create 0640 app adm
su app adm
sharedscripts
postrotate
/usr/bin/systemctl kill --signal=HUP --kill-who=main app.service
endscript
} Use copytruncate only for writers that cannot reopen
copytruncate copies the current file and then truncates the original inode. Writes in the gap can be lost, and copying a busy large file increases I/O and produces a non-atomic snapshot. create has no effect with copytruncate. Prefer application-native reopen, journald, or a logging service; if forced to use copytruncate, measure loss tolerance, schedule away from peaks, and preserve an independent durable log stream.
/var/log/legacy/app.log {
daily
maxsize 250M
rotate 7
copytruncate
compress
missingok
notifempty
} Treat writable log directories and scripts as privilege boundaries
logrotate commonly starts as root. Rotating a file beneath a directory controlled by an unprivileged account can enable symlink or script attacks; current logrotate recommends su for such directories. The selected identity must create, rename, compress, and move files as configured. Keep configuration and script files root-owned and non-writable, specify create modes explicitly, and understand SELinux or AppArmor denials before weakening policy.
namei -l /var/log/app/app.log
stat -c '%A %U:%G %n' /etc/logrotate.conf /etc/logrotate.d/app /var/log/app
sudo logrotate --debug /etc/logrotate.d/app
sudo journalctl --unit=logrotate.service --since today --no-pager Troubleshoot the scheduler, exit status, and reopen separately
A correct stanza does nothing if the scheduler never invokes logrotate. Modern systemd distributions often use logrotate.timer; others use cron. Check the service result, state timestamp, filesystem space, and application descriptor after a cycle. Container images may have neither scheduler. A successful logrotate exit does not prove the application reopened the replacement file or that a remote log shipper consumed the archive.
systemctl status logrotate.timer logrotate.service --no-pager
journalctl --unit=logrotate.service --since today --no-pager
sudo lsof /var/log/app/app.log
df -h /var/log /var/lib
df -i /var/log /var/lib Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



