logrotate
logrotate is a Linux tool that automatically rotates, compresses, and deletes log files. /etc/logrotate.conf is the global configuration file, and per-application configuration files are placed under the /etc/logrotate.d/ directory. You specify the rotation schedule with daily, weekly, or size; compress old logs with compress; and use postrotate to restart a daemon after rotation.
Syntax
# -----------------------------------------------
# Basic structure of a /etc/logrotate.d/ config file
# -----------------------------------------------
# {path to log file} {
# rotation frequency
# number of generations to keep
# compression options
# error handling options
# script to run after rotation
# }
/var/log/kyo-app/*.log {
# -----------------------------------------------
# Rotation frequency (specify one)
# -----------------------------------------------
# daily → Rotates every day
# weekly → Rotates every week
# monthly → Rotates every month
# size {N} → Rotates when the file size exceeds N
# Units: k (kilobytes) / M (megabytes) / G (gigabytes)
# Example: size 100M
daily
# -----------------------------------------------
# Number of generations to keep
# -----------------------------------------------
# rotate {N}
# → Keeps N generations of rotated log files
# → The (N+1)th generation is automatically deleted
rotate 7
# -----------------------------------------------
# Compression settings
# -----------------------------------------------
# compress
# → Compresses rotated logs with gzip (.gz)
compress
# delaycompress
# → Skips compression for the most recent generation; compresses it on the next rotation
# → Use this when a process is still writing to the log file
delaycompress
# -----------------------------------------------
# Error handling and empty file handling
# -----------------------------------------------
# missingok
# → Does not raise an error if the target log file does not exist
missingok
# notifempty
# → Skips rotation if the log file is empty
notifempty
# -----------------------------------------------
# File creation settings
# -----------------------------------------------
# create {permissions} {owner} {group}
# → Creates a new log file with the specified permissions after rotation
create 0640 www-data www-data
# dateext
# → Uses a date suffix instead of a number for rotated filenames
# → Example: app.log.2026-03-25.gz
dateext
# -----------------------------------------------
# Script to run after rotation
# -----------------------------------------------
# postrotate ... endscript
# → Defines a shell script to run after rotation is complete
# → Commonly used to send a signal to a daemon to reopen its log file
postrotate
systemctl reload kyo-app 2>/dev/null || true
endscript
}
# -----------------------------------------------
# Using copytruncate (when restarting the process is not feasible)
# -----------------------------------------------
/var/log/mai-app/*.log {
daily
rotate 14
compress
missingok
notifempty
# copytruncate
# → Copies the log file and then truncates the original to zero bytes
# → Minimizes impact on processes that keep the file descriptor open
# → Use this when you cannot restart the daemon in a postrotate script
copytruncate
}
# -----------------------------------------------
# Using the su directive
# -----------------------------------------------
/var/log/terry-app/*.log {
daily
rotate 30
compress
missingok
# su {user} {group}
# → Runs logrotate itself with the privileges of this user
# → Use this for logs owned by a non-root user
su terry terry
postrotate
kill -HUP $(cat /var/run/terry-app.pid) 2>/dev/null || true
endscript
}
Directive Reference
| Directive | Description |
|---|---|
daily | Rotates logs every day. |
weekly | Rotates logs every week. |
monthly | Rotates logs every month. |
size {N} | Rotates when the file size exceeds N (e.g., 100M). Takes precedence over frequency directives. |
rotate {N} | Keeps N generations of rotated log files. The (N+1)th generation is automatically deleted. |
compress | Compresses rotated logs with gzip. |
delaycompress | Delays compression of the most recent generation until the next rotation. Used together with compress. |
missingok | Does not raise an error if the target log file does not exist. |
notifempty | Skips rotation if the log file is empty. |
create {permissions} {user} {group} | Creates a new log file with the specified permissions after rotation. |
dateext | Uses a date suffix (e.g., .2026-03-25) instead of a sequential number for rotated filenames. |
postrotate / endscript | Defines a shell script to run after rotation is complete. Commonly used to send signals to daemons. |
prerotate / endscript | Defines a script to run before rotation begins. |
copytruncate | Copies the original file and truncates it to zero bytes. Use this when you cannot restart the process. |
su {user} {group} | Runs logrotate with the privileges of the specified user. Use this for logs owned by a non-root user. |
sharedscripts | Runs the postrotate script only once even when multiple files are matched by a wildcard. |
dateformat {format} | Specifies the date format for dateext (e.g., -%Y%m%d). |
maxage {N} | Deletes rotated log files older than N days. |
minsize {N} | Skips rotation if the file size is smaller than N. Evaluated together with the frequency condition (AND). |
Examples
/etc/logrotate.d/kyo-app (log rotation config for an application)
# -----------------------------------------------
# logrotate config for the kyo-app web application
# /etc/logrotate.d/kyo-app
# -----------------------------------------------
/var/log/kyo-app/access.log
/var/log/kyo-app/error.log {
# Rotates every day
daily
# Keeps 30 generations (approximately one month)
rotate 30
# Compresses rotated logs with gzip
compress
# Delays compression for the most recent generation
# (prevents compressing a file the app is still writing to)
delaycompress
# Does not raise an error if the log file does not exist
missingok
# Skips rotation for empty files
notifempty
# Creates a new log file after rotation
create 0640 www-data www-data
# Appends a date to the filename (e.g., access.log-2026-03-25.gz)
dateext
# Runs postrotate only once even when multiple files match the wildcard
sharedscripts
# After rotation, sends USR1 to Nginx to make it reopen the log file
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid) 2>/dev/null || true
endscript
}
Run the following command:
$ sudo logrotate -d /etc/logrotate.d/kyo-app WARNING: logrotate in debug mode does nothing except printing debug messages! Consider using verbose mode (-v) instead if this is not what you want. reading config file /etc/logrotate.d/kyo-app Allocating hash table for state file, size 64 entries Adding /var/log/kyo-app/access.log Adding /var/log/kyo-app/error.log Handling 2 logs rotating pattern: /var/log/kyo-app/access.log after 1 days (30 rotations) empty log files are not rotated, old logs are removed considering log /var/log/kyo-app/access.log log does not need rotating (log has been already rotated) rotating pattern: /var/log/kyo-app/error.log after 1 days (30 rotations) empty log files are not rotated, old logs are removed considering log /var/log/kyo-app/error.log log does not need rotating (log has been already rotated) $ sudo logrotate -v /etc/logrotate.d/kyo-app reading config file /etc/logrotate.d/kyo-app rotating log /var/log/kyo-app/access.log, log->rotateCount is 30 dateext suffix '-2026-03-25' glob pattern '-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]' renaming /var/log/kyo-app/access.log.29.gz to /var/log/kyo-app/access.log.30.gz (rotatecount 30, logstart 1, i 29), ... compressing log with: /bin/gzip $ sudo logrotate --force /etc/logrotate.d/kyo-app (--force rotates regardless of the normal conditions)
Checking the global config /etc/logrotate.conf and running logrotate manually
# ----------------------------------------------- # Check the default settings in /etc/logrotate.conf # ----------------------------------------------- cat /etc/logrotate.conf
Run the following command:
$ cat /etc/logrotate.conf # see "man logrotate" for details # global options do not affect preceding include directives # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # use date as a suffix of the rotated file dateext # uncomment this if you want your log files compressed #compress # packages drop log rotation information into this directory include /etc/logrotate.d # system-specific logs may also be configured here
The following example demonstrates this:
# ----------------------------------------------- # Run logrotate manually against all configurations # ----------------------------------------------- # Check all configurations in debug mode (makes no actual changes) sudo logrotate -d /etc/logrotate.conf # List rotated log files ls -lh /var/log/kyo-app/ # Check the state file (records the last rotation timestamp) cat /var/lib/logrotate/status | grep kyo-app
Running these commands produces the following output:
$ ls -lh /var/log/kyo-app/ total 2.1M -rw-r----- 1 www-data www-data 48K Mar 25 09:12 access.log -rw-r----- 1 www-data www-data 12K Mar 24 00:00 access.log-20260324.gz -rw-r----- 1 www-data www-data 9K Mar 23 00:00 access.log-20260323.gz -rw-r----- 1 www-data www-data 3K Mar 25 09:12 error.log -rw-r----- 1 www-data www-data 1K Mar 24 00:00 error.log-20260324.gz $ cat /var/lib/logrotate/status | grep kyo-app "/var/log/kyo-app/access.log" 2026-3-25-0:0:0 "/var/log/kyo-app/error.log" 2026-3-25-0:0:0
Overview
logrotate is invoked periodically by cron or a systemd timer (logrotate.timer). It prevents log files from growing without bound and manages disk usage by compressing and deleting old logs. The common practice is to define global defaults in /etc/logrotate.conf and override them per application in files under /etc/logrotate.d/. The logrotate -d debug mode is useful for safely verifying that your configuration is recognized correctly. If you forget the postrotate block that sends a signal to the daemon after rotation, the daemon will keep writing to the old file descriptor, so be careful. For viewing actual system logs, journalctl is also a useful companion tool.
If you find any errors or copyright issues, please contact us.