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.