The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Debug a configurationsudo logrotate --debug /etc/logrotate.confView examples
Run verboselysudo logrotate --verbose /etc/logrotate.confView examples
Test with isolated statesudo logrotate --state /run/app-logrotate.state \ --verbose /etc/logrotate.d/appView examples
Force a rotationsudo logrotate --force /etc/logrotate.d/appView examples
Rotate by sizesize 100MView examples
Cap between intervalsmaxsize 500MView examples
Keep archive generationsrotate 14View examples
Expire old archivesmaxage 90View examples
Use sortable date suffixesdateextView examples
Compress archivescompressView examples
Delay compressiondelaycompressView examples
Create replacement securelycreate 0640 app admView examples
Run scripts oncesharedscriptsView examples
Signal the writerpostrotateView examples
Copy then truncate in placecopytruncateView examples
Drop rotation identitysu app admView examples
Inspect rotation schedulingsystemctl status logrotate.timer logrotate.service \ --no-pagerView 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

01

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.

Validate and inspect scheduling
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
Back to quick reference ↑
02

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.

Daily policy with an emergency size bound
/var/log/app/app.log {
    daily
    maxsize 500M
    rotate 30
    maxage 90
    dateext
    missingok
    notifempty
}
Back to quick reference ↑
03

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.

Compress older generations
/var/log/app/app.log {
    daily
    rotate 30
    compress
    delaycompress
    dateext
}
Back to quick reference ↑
04

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.

Rotate and request a safe reopen
/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
}
Back to quick reference ↑
05

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.

Document a legacy exception
/var/log/legacy/app.log {
    daily
    maxsize 250M
    rotate 7
    copytruncate
    compress
    missingok
    notifempty
}
Back to quick reference ↑
06

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.

Audit configuration and path ownership
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
Back to quick reference ↑
07

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.

Verify one completed cycle
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
Back to quick reference ↑

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. logrotate Projectlogrotate(8) Manual Pageman7.org
  2. logrotate Projectlogrotate Source and Documentationgithub.com
  3. systemd Projectsystemd.timerfreedesktop.org
  4. systemd Projectsystemctlfreedesktop.org
  5. lsof Projectlsof Manual Pagelsof.readthedocs.io

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback