Why does my CentOS logrotate run at random times?

Solution 1:

The key is knowing that CentOS runs the scripts in /etc/cron.{daily,weekly,monthly} from anacron... /etc/anacrontab is setting RANDOM_DELAY, which does what you might expect (it delays up to RANDOM_DELAY minutes before starting the job)...

# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7       25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly

Setting RANDOM_DELAY=0 / START_HOURS_RANGE=3 fixed the problem...

EDIT

After further thought, I am going to remove anacron and install normal vixie cron...

Solution 2:

Not the answer, but I recently was trying to figure this out for another reason and couldn't find any documentation on how Redhat 6, Centos, etc run cron. Here's what I reverse engineered:

  1. crond still runs at system startup - it loads all files in /etc/cron.d
  2. /etc/cron.d/0hourly runs all files in /etc/cron.hourly
  3. /etc/cron.hourly/0anacron runs anacron
  4. anacron loads /etc/anacrontab
  5. /etc/anacrontab runs (via run-parts) /etc/cron.daily, /etc/cron.weekly and /etc/cron.monthly

So, it is more complicated than in previous versions.

It's possible to restore the old behavior by adding the hourly, weekly and monthly entries back into /etc/crontab (which is now empty), but anacrontab will need to be updated too. This may or may not break future updates...


Solution 3:

Other answers cover how but not necessarily why. The reason is to keep simultaneous nightly cron jobs from killing your infrastructure. (Imagine shared storage, or maybe 1000 servers running on one VM host, or just nightly jobs which hit some networked service.)

I always solve this problem for log rotation in specific on my systems by moving the specific log rotation job from cron.daily to an entry with a hard-coded time in cron.d. That way, you still get the staggered runs for services like updatedb where the time really isn't essential, but consistent times for log rotation.

Of course, when you get to a certain size, you'll want all of your logs sent off the host to a logserver anyway, and then the rotation time of the files on the individual nodes are less important, since those are just there for convenience (usually following the tail of the file) or as a last-resort fallback. Then, you'd definitely set the rotation on your log server to be systematic.