Log Rotation with logrotate: Linux System Management

Configure log rotation to manage disk space and maintain log files. This guide covers logrotate configuration, compression, retention policies, and automation.

Linux log files with rotation cycle visualization

Introduction

Log files capture essential information about system operations, application behavior, and security events. Without proper management, these files consume increasing disk space until they threaten system stability. Log rotation solves this problem by regularly archiving, compressing, and removing old log files according to configured policies.

The logrotate utility, included with virtually all Linux distributions, automates log management tasks. It handles rotation based on size, time, or both; compresses old logs to save space; creates new log files with proper permissions; and can execute scripts before and after rotation for custom processing. Understanding logrotate configuration enables you to maintain clean log directories while preserving historical data for troubleshooting and compliance.

This comprehensive guide walks you through logrotate configuration for various scenarios. You will learn the configuration syntax, create policies for different log types, implement compression and retention strategies, and troubleshoot common rotation issues. By the end, you will confidently manage log files across your Linux infrastructure.

Understanding Log Rotation

Log rotation serves multiple purposes beyond simple disk space management.

Regular rotation prevents any single log file from growing indefinitely, which would slow file operations and make log analysis impractical. Compression reduces the storage footprint of retained logs significantly—gzip typically achieves 70-90% compression ratios on text-based logs. Time-based retention policies balance storage costs against the need to investigate historical incidents.

Logrotate operates through cron, executing daily by default. During execution, it checks each configured log file against its rotation policy and performs rotations as needed. The utility handles many edge cases: it creates new log files with correct ownership before rotating old ones, maintains symlinks for current logs, and prevents race conditions in applications that actively write logs.

Basic logrotate Configuration

The main configuration file and drop-in directories define rotation policies.

Configuration File Structure

# /etc/logrotate.conf
# Global settings apply to all log files

# Rotate logs weekly (daily, weekly, monthly, yearly)
weekly

# Keep 4 weeks of backlogs (number of rotations to keep)
rotate 4

# Create new empty log files after rotation
create

# Date extensions for rotated files
dateext
dateformat -%Y%m%d

# Location for state file (tracks rotation status)
state /var/lib/logrotate/status

# Log compression (uncomment to enable by default)
compress
compresscmd /usr/bin/xz
uncompresscmd /usr/bin/unxz

# Size-based rotation (overrides time if both specified)
# size 100M

# Error emails
mail logadmin@example.com

# Include additional configuration files
include /etc/logrotate.d

Logrotate.d Directory

Individual configurations in /etc/logrotate.d/ override global settings:

# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
}

Creating Custom Rotation Policies

Configure rotation for application-specific logs.

Application Log Examples

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    notifempty
    create 0640 www-data www-data
    dateext
    dateformat -%Y%m%d_
    postrotate
        systemctl reload myapp 2>/dev/null || true
    endscript
}

Multiple Log Patterns

Handle complex log structures with pattern matching:

# /etc/logrotate.d/apache2
/var/log/apache2/*.log /var/log/apache2/*/*.log {
    daily
    rotate 60
    compress
    delaycompress
    notifempty
    create 640 root adm
    sharedscripts
    postrotate
        if [ -f /var/run/apache2/apache2.pid ]; then
            service apache2 reload > /dev/null
        fi
    endscript
    rotate 90
}

Syslog Rotation

# /etc/logrotate.d/rsyslog
/var/log/syslog
/var/log/mail.log
/var/log/kern.log
/var/log/auth.log
{
    daily
    rotate 30
    compress
    delaycompress
    notifempty
    create 640 root syslog
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate
    endscript
}

Rotation Options Reference

Understanding options enables precise policy control.

Timing Options

# Time-based rotation
daily       # Rotate every day
weekly      # Rotate on first day of week
monthly     # Rotate on first day of month
yearly      # Rotate once per year

# Size-based rotation (alternative or additional trigger)
size 100M   # Rotate when file exceeds 100MB
size 1G     # Rotate when file exceeds 1GB
size 100k   # Rotate when file exceeds 100KB

Retention Options

rotate 14   # Keep 14 rotated files (delete older)
maxage 90   # Remove files older than 90 days

Compression Options

compress            # Enable compression (gzip by default)
compresscmd /usr/bin/xz    # Use xz instead of gzip
uncompresscmd /usr/bin/unxz
compressext .xz
delaycompress      # Don't compress immediately (wait for next rotation)
nocompress         # Disable compression for this block
compresscmd bzip2

File Creation Options

create 640 root admin    # Create new log with permissions
createoldcopy 640 root admin  # Create with old file's permissions
nocreate             # Don't create new log file

Filtering Options

notifempty       # Don't rotate empty files
ifempty          # Rotate even if empty files
minsize 1M       # Don't rotate until file reaches size (and time met)
maxsize 100M     # Force rotation if file exceeds size
start count     # Start numbering at count instead of 1
dateext         # Use date instead of numbers in filenames
dateformat -%Y%m%d_%H%M%S  # Date format for filenames

Advanced Configuration

Advanced options handle complex scenarios and integration requirements.

Pre and Post Rotation Scripts

Execute commands before and after rotation:

# /etc/logrotate.d/application
/var/log/myapp/*.log {
    daily
    rotate 7
    compress
    create 640 appuser appuser
    
    # Commands to run BEFORE rotation
    prerotate
        if [ -f /var/run/myapp.pid ]; then
            /usr/local/bin/myapp-rotate-signals
        fi
    endscript
    
    # Commands to run AFTER rotation
    postrotate
        systemctl reload myapp 2>/dev/null || true
    endscript
}

Shared Scripts

Execute scripts once per rotation regardless of matching files:

# /etc/logrotate.d/webapp
/var/log/webapp/*.log /var/log/webapp/**/*.log {
    daily
    rotate 30
    compress
    sharedscripts
    
    # Runs once if ANY files are rotated
    postrotate
        /usr/local/bin/notify-log-rotation
    endscript
}

Firstaction and Lastaction

Execute scripts at very beginning and end:

/var/log/complex/*.log {
    daily
    rotate 5
    firstaction
        echo "Starting rotation at $(date)" >> /var/log/rotation-audit.log
    endscript
    
    lastaction
        echo "Completed rotation at $(date)" >> /var/log/rotation-audit.log
    endscript
}

Conditional Execution

# Rotate only on specific days (weekends)
/var/log/weekly-report/*.log {
    weekly
    rotate 12
    ifempty
    create 640 root root
    postrotate
        [ -x /usr/local/bin/weekly-report-email ] && /usr/local/bin/weekly-report-email
    endscript
}

Application-Specific Examples

Real-world configurations for common applications.

Docker Logs

# /etc/logrotate.d/docker
/var/lib/docker/containers/*/*.log {
    daily
    rotate 7
    compress
    size 100M
    missingok
    notifempty
    dateext
    dateformat -%Y%m%dT%H%M%S
    postrotate
        /usr/bin/docker kill -s USR1 $(docker ps -q) 2>/dev/null || true
    endscript
}

PostgreSQL Logs

# /etc/logrotate.d/postgresql
/var/log/postgresql/postgresql*.log {
    daily
    rotate 14
    compress
    delaycompress
    create 640 postgres postgres
    postrotate
        [ -f /var/run/postgresql.pid ] && kill -HUP $(cat /var/run/postgresql.pid) 2>/dev/null || true
    endscript
}

MySQL Logs

# /etc/logrotate.d/mysql-server
/var/log/mysql/*.log {
    daily
    rotate 7
    compress
    create 640 mysql mysql
    postrotate
        mysqladmin flush-logs
    endscript
}

SSH Logs

# /etc/logrotate.d/openssh-server
/var/log/auth.log /var/log/secure {
    daily
    rotate 30
    compress
    delaycompress
    create 640 root syslog
    sharedscripts
    postrotate
        systemctl reload rsyslog 2>/dev/null || true
    endscript
}

Troubleshooting Log Rotation

Rotation issues manifest in various ways—missing logs, disk space problems, or errors in rotation scripts.

Manual Rotation Testing

# Test configuration syntax
logrotate -d /etc/logrotate.conf

# Force one rotation cycle
logrotate -f /etc/logrotate.conf

# Verbose output for debugging
logrotate -v /etc/logrotate.conf

# Check specific configuration
logrotate -d /etc/logrotate.d/myapp

Common Issues

# Logs not rotating - check state file
cat /var/lib/logrotate/status | grep myapp

# Files too large - verify size limits
logrotate -d /etc/logrotate.d/myapp

# Permission errors - check file ownership
ls -la /var/log/myapp/

# Script errors - run scripts manually
/usr/local/bin/myapp-rotate-signals

Logrotate Cron

# Check cron configuration
cat /etc/cron.daily/logrotate

# View cron execution logs
cat /var/log/cron.log | grep logrotate

# Manual cron execution
/etc/cron.daily/logrotate

Monitoring and Alerts

Implement monitoring to ensure rotation operates correctly.

Rotation Verification

# Script to verify rotation occurred
#!/bin/bash
# /usr/local/bin/verify-logrotate

RECIPIENT="admin@example.com"
SUBJECT="Log Rotation Alert"

for logfile in /var/log/myapp/*.log; do
    if [ -f "$logfile.1.gz" ]; then
        echo "$logfile was rotated"
    else
        echo "$logfile NOT rotated" | mail -s "$SUBJECT" $RECIPIENT
    fi
done

Disk Space Monitoring

# Check log directory sizes
du -sh /var/log/*/ | sort -h

# Find largest log files
find /var/log -type f -exec du -h {} \; | sort -rh | head -20

# Monitor with cron
*/30 * * * * /usr/local/bin/check-log-space

Conclusion

Log rotation protects your systems from log-related disk exhaustion while preserving historical data for troubleshooting. Configure logrotate policies that balance storage costs against retention needs, add compression for space efficiency, and implement monitoring to verify rotation executes correctly.

For distributed systems, consider centralized logging solutions that aggregate logs from multiple servers while implementing rotation at the collection point. Local rotation policies still matter for applications that write directly to disk, even with centralized logging.


Related Guides: