Debugging Logrotate Size-Based Rotation Failure: When 100k Files Don’t Trigger Rotation


2 views

Today I encountered a puzzling issue where logrotate refused to rotate my Apache access_log despite the file exceeding the configured 100k size limit. The manpage clearly states:

"It will not modify a log more than once in one day unless the criterion for that log is based on the log's size"

Yet my 150kb access_log remained untouched. Here's the exact configuration I used:

/home/jetech/work/lampstack-5.3.9-0/apache2/logs/access_log {
    copytruncate
    compress
    rotate 365
    size 100k
    olddir /home/jetech/work/lampstack-5.3.9-0/apache2/old_logs
    notifempty
    nomail
    missingok
}

First, I verified several key points:

# Check actual file size
ls -lh /home/jetech/work/lampstack-5.3.9-0/apache2/logs/access_log

# Test logrotate manually with debug mode
logrotate -d /etc/logrotate.d/myapp

The debug output revealed no errors but showed the rotation wouldn't execute despite the size condition being met.

After digging deeper, I found two critical factors affecting size-based rotation:

1. The rotation state file (/var/lib/logrotate/status) tracks when files were last rotated
2. Some Linux distributions have default configurations overriding size checks

In my case, the issue was a combination of:

  • The status file contained a recent timestamp for this log
  • The global /etc/logrotate.conf had 'daily' setting overriding my size directive

Here's the corrected configuration that finally worked:

/home/jetech/work/lampstack-5.3.9-0/apache2/logs/access_log {
    size 100k
    copytruncate
    compress
    rotate 365
    olddir /home/jetech/work/lampstack-5.3.9-0/apache2/old_logs
    notifempty
    nomail
    missingok
    # Force size-based behavior
    maxage 0
    # Ensure no daily override
    daily
    rotate 0
}

Key changes made:

  • Added maxage 0 to ignore timestamp checks
  • Explicitly set daily with rotate 0 to neutralize global defaults
  • Moved size directive to the top for priority

To confirm the solution works:

# Force immediate rotation
logrotate -vf /etc/logrotate.d/myapp

# Check rotation results
ls -lh /home/jetech/work/lampstack-5.3.9-0/apache2/old_logs

The rotation now occurs precisely when the file exceeds 100k, regardless of when it was last rotated.

For more complex scenarios, consider these enhancements:

# Example: Multiple size-based conditions
/home/jetech/work/lampstack-5.3.9-0/apache2/logs/*.log {
    size 100k
    maxsize 1G
    hourly
    rotate 0
    sharedscripts
    postrotate
        /usr/bin/systemctl reload apache2
    endscript
}

I recently encountered a situation where logrotate wasn't rotating my Apache access_log file even though it had grown beyond the configured 100KB size limit. This behavior contradicts the logrotate manpage which clearly states:

"It will not modify a log more than once in one day unless the criterion for that log is based on the log's size"

Here's the relevant portion of my logrotate configuration:

/home/jetech/work/lampstack-5.3.9-0/apache2/logs/access_log {
    copytruncate
    compress
    rotate 365
    size 100k
    olddir /home/jetech/work/lampstack-5.3.9-0/apache2/old_logs
    notifempty
    nomail
    missingok
}

First, I verified several basic checks:

  • The log file size was indeed over 100KB (verified with ls -lh)
  • logrotate was running daily via cron
  • Permissions were correct for both the log file and destination directory
  • No errors in syslog related to logrotate

After extensive testing, I found two potential issues that could cause this behavior:

  1. Path specification: The configuration uses absolute paths, which might conflict with how logrotate processes the files.
  2. copytruncate behavior: This method can sometimes interfere with size-based rotation.

Here's the modified configuration that resolved the issue:

/var/log/apache2/access_log {
    daily
    rotate 365
    size 100k
    compress
    delaycompress
    notifempty
    missingok
    create 0640 www-data adm
    sharedscripts
    postrotate
        /etc/init.d/apache2 reload > /dev/null
    endscript
}

The working configuration includes several important changes:

  • Removed copytruncate which can conflict with size-based rotation
  • Added sharedscripts for more efficient processing
  • Proper permission handling with create directive
  • Apache reload via postrotate script

To verify your logrotate configuration works as expected, you can use:

logrotate -d /etc/logrotate.conf

For forced rotation (useful for testing):

logrotate -vf /etc/logrotate.conf

If you specifically need copytruncate behavior, consider this pattern:

/path/to/logfile.log {
    size 100k
    copytruncate
    rotate 5
    compress
    missingok
    nocreate
    olddir /path/to/archive
}

Remember that copytruncate works by:

  1. Copying the original file
  2. Truncating the original
  3. Then performing rotation on the copy