Understanding and Fixing Random logrotate Execution Times in CentOS: A Sysadmin’s Guide


2 views

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