Home/Engineer/Linux / Shell/Complete logrotate Guide — A…
Linux / ShellIntermediatelinuxlogrotatelogsrotation

Complete logrotate Guide — Automatic Log Rotation and Compression

This guide explains how to automatically rotate, compress, and retain log files with logrotate. It covers the /etc/logrotate.conf and /etc/logrotate.d layout, the rotate, size, compress, and postrotate directives, copytruncate vs create, cr

Contents
  1. What is logrotate?
  2. How it works and when it runs
  3. Global defaults — /etc/logrotate.conf
  4. Writing a per-app config — /etc/logrotate.d/myapp
  5. Size-based rotation
  6. create vs copytruncate
  7. prerotate / postrotate scripts
  8. Testing and debugging
  9. Common problems
  10. Recap

What is logrotate?

When a server runs for a long time, log files under /var/log grow without bound. Left unchecked, the disk fills up and services stop; a multi-GB single log is hard even to search. logrotate is the standard tool that automates this: at a set interval or size it rotates logs into new files and compresses or deletes the old ones.

The basic idea of rotation looks like this.

CODE
app.log ←
app.log.1 ←
app.log.2.gz ←
app.log.3.gz
...

When a new file is created, the numbers shift by one, and the oldest file beyond the retention limit is deleted.


How it works and when it runs

logrotate is not a daemon; it is a one-shot command that cron or a systemd timer runs once a day.

DistroTrigger
Traditional/etc/cron.daily/logrotate
systemd-basedlogrotate.timer → logrotate.service
Bash
# systemd check
systemctl list-timers logrotate.timer
systemctl status logrotate.timer

The configuration entry point is /etc/logrotate.conf, which ends with include /etc/logrotate.d to load per-app configs. The standard practice is to put package- or application-specific settings as files under /etc/logrotate.d/.


Global defaults — /etc/logrotate.conf

CODE
#
weekly

# 4 ( 4)
rotate 4

# after file
create

# file (app.log-20260618)
dateext

# file
compress

# settings
include /etc/logrotate.d

If an individual config under /etc/logrotate.d repeats the same directive, it overrides the global value.


Writing a per-app config — /etc/logrotate.d/myapp

A practical example for a web application log.

CODE
/var/log/myapp/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    dateext
    create 0640 appuser appgroup
    sharedscripts
    postrotate
        systemctl reload myapp >/dev/null 2>&1 || true
    endscript
}

What each directive does:

DirectiveRole
daily / weekly / monthlyRotation interval
rotate 14Keep 14 copies, then delete
missingokSkip without error if the log file is missing
notifemptyDo not rotate if the file is empty
compressgzip-compress rotated files
delaycompressDelay compression of the most recently rotated file by one cycle
dateextUse a date suffix instead of a sequence number
create 0640 user groupCreate the new log with the given mode and ownership
sharedscriptsRun scripts once for the whole wildcard match, not once per file
postrotate ... endscriptCommands to run immediately after rotation

When you need to unpack rotated .gz logs or bundle several logs for handoff, see Linux tar, gzip, and zstd decompression cheat sheet.

Size-based rotation

Use this when you want to cut by size rather than time.

CODE
/var/log/nginx/access.log {
    size 100M
    rotate 10
    compress
    missingok
    create 0640 www-data adm
    postrotate
 # nginx file
        [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
    endscript
}
DirectiveMeaning
size 100MRotate when the file exceeds 100MB (interval is ignored; size is checked on every run)
maxsize 100MRotate even before the interval if this size is exceeded
minsize 10MDo not rotate at the interval if the file is smaller than this

Using size alone ignores time conditions such as daily/weekly. If you want “weekly, or whenever it exceeds 100MB”, combine weekly with maxsize 100M.


create vs copytruncate

These are the two most important rotation strategies. Choose based on how the application handles its log file.

MethodBehaviorBest when
create (default)Renames the existing file with mv and creates a new oneThe app can receive a reopen signal (SIGHUP, etc.) from postrotate
copytruncateCopies the original, then truncates it to 0 bytesYou cannot restart or signal the app and it keeps the file handle open
CODE
/var/log/legacy-app/output.log {
    daily
    rotate 7
    compress
    copytruncate
}

If you use create but never send a reopen signal, the app keeps writing to the old file handle that was mv'd (already renamed). The new app.log stays empty and disk usage never drops. If the app cannot be signaled, use copytruncate, but be aware that logs written in the brief window between copy and truncate can be lost.


prerotate / postrotate scripts

Run commands before or after rotation. The usual use is signaling a service to open the new file.

CODE
postrotate
 # systemd reload
    systemctl reload rsyslog >/dev/null 2>&1 || true
endscript

Without sharedscripts, the script runs once per file matched by the wildcard. A service reload usually needs to happen only once, so pairing it with sharedscripts is the common pattern.


Testing and debugging

After changing a config, verify immediately instead of waiting for cron.

Bash
# 1) ( X) —
logrotate --debug /etc/logrotate.d/myapp

# 2) (/ when)
sudo logrotate --force /etc/logrotate.d/myapp

# 3) settings run
sudo logrotate --force /etc/logrotate.conf

# 4) when check
cat /var/lib/logrotate/logrotate.status

--debug includes --verbose and does not change anything. It is the safe first step when checking a config on a production server. If rotation is not happening, check whether that log's last rotation date was updated in the status file.


Common problems

SymptomCause / fix
Rotation ran but disk usage did not dropcreate without a reopen signal → use copytruncate or add a postrotate signal
New log cannot be created due to permissionsSet create mode/owner and check parent directory permissions
Config is ignoredExecute bit or extension issues on the /etc/logrotate.d/ file, or it is not included from .conf. Watch for extra . (dots) in the filename
"skipping ... because parent directory has insecure permissions"Add an su user group directive or fix directory permissions
One compressed file seems missingCaused by delaycompress (the newest rotated file is compressed on the next cycle) — expected behavior

Recap

ItemKey point
Who runs itcron.daily or logrotate.timer (not a daemon)
Config locationGlobal /etc/logrotate.conf, per-app /etc/logrotate.d/
Scheduledaily/weekly/monthly or size/maxsize
Retention countrotate N
Compressioncompress + delaycompress
New file handlingcreate (needs a signal) vs copytruncate (apps that cannot be signaled)
Post-processingpostrotate ... endscript + sharedscripts
Verificationlogrotate --debug, --force

Because logrotate ships on almost every Linux server, getting into the habit of dropping a config file into /etc/logrotate.d/ whenever you deploy a new service is the most reliable way to prevent outages caused by a full disk.

#logrotate#logs#rotation#cron#maintenance
Editorial note

AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us

Topic-related official docs (auto-linked · not per-claim sources)Linux man pages ↗

Questions & answers

Ask a question about this guide. We'll review and reply.