On CentOS/RHEL systems, the default logrotate behavior might surprise you. The random execution times stem from the anacron
system (for daily jobs) and a built-in randomization feature in the cron.daily
mechanism. Here's what happens:
# Default cron job for logrotate (usually in /etc/cron.daily/logrotate)
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
The cron job doesn't run at exactly midnight due to:
- anacron randomization: Default delay of up to 45 minutes for background jobs
- cron.daily spread: The /etc/crontab often contains a built-in random delay:
# Example from /etc/crontab
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
Here are three reliable solutions:
Option 1: Direct Cron Scheduling
Create a custom cron job that bypasses the daily randomization:
# Add to /etc/crontab or a custom cron file in /etc/cron.d/
0 2 * * * root /usr/sbin/logrotate /etc/logrotate.conf
Option 2: Systemd Timer Alternative
Modern systems can use:
# /etc/systemd/system/logrotate.timer
[Unit]
Description=Daily log rotation
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
# /etc/systemd/system/logrotate.service
[Unit]
Description=Rotate log files
Documentation=man:logrotate(8)
[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf
Option 3: Disable Randomization
Edit the anacrontab to remove delays:
# /etc/anacrontab
# Set RANDOM_DELAY to 0
RANDOM_DELAY=0
After making changes, verify with:
# Check when the job will run next
systemctl list-timers
# Force a test run (add -v for verbose output)
logrotate -vf /etc/logrotate.conf
For time-sensitive applications, consider these additional measures:
# Example config with time-critical rotation
/var/log/time-sensitive/*.log {
missingok
rotate 7
daily
create 0640 appuser appgroup
dateext
dateformat -%Y%m%d-%H%M%S
sharedscripts
prerotate
/usr/bin/systemctl stop appservice
endscript
postrotate
/usr/bin/systemctl start appservice
endscript
}
Many CentOS/RHEL administrators notice that their logrotate
jobs don't execute at consistent times despite specifying daily
rotation. Instead, rotation occurs with a seemingly random offset of ±1 hour from the expected time. This behavior isn't actually random - it's by design.
The root cause lies in how the cron.daily
mechanism operates. On CentOS/RHEL systems, the daily cron jobs (including logrotate) are triggered by /etc/cron.daily/logrotate
, but with an intentional randomization:
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
This script is called by anacron
(not regular cron) with built-in jitter to prevent system overload when many servers might run maintenance tasks simultaneously.
If you need precise rotation times, you have several options:
Option 1: Create a Dedicated cron Job
Override the default behavior by creating a specific cron job:
# crontab -e
# Run logrotate daily at 4:05 AM
5 4 * * * /usr/sbin/logrotate /etc/logrotate.conf
Option 2: Modify the anacron Configuration
Edit /etc/anacrontab
to remove the randomization:
# Original line with randomization:
1 5 cron.daily nice run-parts /etc/cron.daily
# Modified version without random delay:
1 0 cron.daily nice run-parts /etc/cron.daily
After making changes, verify the new behavior:
# Check when logrotate last ran
grep logrotate /var/log/cron
# Force a test run
/usr/sbin/logrotate -vf /etc/logrotate.conf
- System updates may overwrite
/etc/anacrontab
changes - Consider server load when choosing fixed times
- For clustered environments, stagger rotation times across nodes
- Always test configuration changes with
-v
(verbose) or-d
(debug) flags