Understanding Logrotate Precedence: When Size and Daily Directives Conflict in Linux Log Rotation


2 views

When configuring logrotate with both size and daily parameters, many administrators expect a boolean OR behavior where rotation occurs when either condition is met. However, the actual implementation shows that size takes precedence over daily when both directives are present.

The behavior is documented in logrotate's man pages (run man logrotate). The key section states:

"When using the 'size' parameter, logrotate will check the log file size
regardless of the time period specified by 'daily', 'weekly', etc."

Here's a typical configuration that demonstrates the issue:

/var/log/myapp.log {
    daily
    size 100M
    rotate 7
    compress
    missingok
    notifempty
}

In this case, the rotation will only occur when the log reaches 100MB, regardless of whether a day has passed.

To achieve true OR behavior, you need separate configurations:

# Configuration for size-based rotation
/var/log/myapp.log {
    size 100M
    rotate 7
    compress
    missingok
    notifempty
}

# Configuration for time-based rotation (run separately)
/var/log/myapp.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
}

For hourly runs (as mentioned in the question), you might use:

# Hourly size check
0 * * * * /usr/sbin/logrotate /etc/logrotate.d/myapp_size

# Daily time check (runs at midnight)
0 0 * * * /usr/sbin/logrotate /etc/logrotate.d/myapp_daily

Another method is to use a custom script that checks both conditions:

#!/bin/bash
LOG=/var/log/myapp.log
SIZE_LIMIT=100000000  # 100MB in bytes
DAY_LIMIT=1           # 1 day

if [ $(find $LOG -mtime +$DAY_LIMIT 2>/dev/null) ] || \
   [ $(stat -c%s $LOG) -gt $SIZE_LIMIT ]; then
    /usr/sbin/logrotate -f /etc/logrotate.d/myapp_combined
fi

When configuring logrotate with both size and daily parameters, many administrators expect these conditions to work as a logical OR operation. However, the actual behavior is that size takes precedence over daily when both directives are present in the configuration. This behavior is documented in the logrotate source code and man pages, though not explicitly stated as a precedence rule.

From examining the logrotate source code (particularly in rotate.c), the rotation checks follow this order:

1. Check for size threshold
2. Check for time-based rotation (daily/weekly/monthly)
3. Check for forced rotation (via -f flag)

The man page (man 8 logrotate) mentions this indirectly: "If size is given, the log will be rotated when it grows bigger than size bytes, even before the specified time interval."

Here's a typical configuration showing both directives:

/var/log/myapp.log {
    daily
    size 100M
    rotate 7
    compress
    missingok
    notifempty
}

In this case, the log will only rotate when it exceeds 100MB, effectively ignoring the daily directive.

To achieve proper OR behavior between size and time-based rotation, you need two separate configurations:

# Size-based rotation
/var/log/myapp.log {
    size 100M
    rotate 7
    compress
    missingok
    notifempty
    lastaction
        # Force time-based rotation check
        /usr/sbin/logrotate -f /etc/logrotate.d/myapp_time
    endscript
}

# Time-based rotation
/var/log/myapp.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
}

Note this requires logrotate to be run more frequently than daily (e.g., hourly cron job).

For mission-critical applications:

  • Separate size and time configurations as shown above
  • Ensure logrotate runs frequently enough (hourly is common)
  • Monitor rotation success via /var/lib/logrotate.status
  • Consider using copytruncate for applications that can't handle log file moves

For more complex rotation needs, consider:

# Using dateext to avoid timestamp confusion
dateext
dateformat -%Y%m%d-%s

# Combining with maxage to clean old logs
maxage 30

Or implement custom rotation logic through postrotate scripts.