[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

PROPOSAL to serialize cron.{daily,weekly,monthly}



Please inform me if there's a better place to (cross)post this.

Current Situation:
cron.daily, cron.weekly, and cron.monthly gets triggered off at specific
times (everyday at 6:25, Sunday at 6:47 and 1st of the month at 6:52,
respectively) regardless of whether previous batch of maintenance scripts
has finished or not. This may result in parallel execution of scripts from
several batches, although each batch in itself is serialized. This, in
turn, can cause consequences ranging from wrong output to fatal script
clash. For instance a script from cron.daily might be scanning the volumes
for viruses, while a script from cron.weekly kicks in, force-unmounts
several volumes (killing the processes using those volumes BTW) and starts
backing up them. Examples are endless.

Basic Circumvention:
Once, I had used to put no home-made scripts in cron.weekly and
cron.monthly, but a zzz-daily script in cron.daily directory, which runs
as the last script. In zzz-daily I was checking for day of the week, and
if it was Sunday I was calling a huge monolithic "weekly maintenance"
script. Likewise, right after that in zzz-daily, I was checking for 1st of
month and calling a monolithic "monthly maintenance" script. While this
works, it had 2 drawbacks:
1. It defeats the original idea of cron.{daily,weekly,monthly} scheme.
2. It doesn't cater for daily/weekly/monthly scripts put there by
packages. So it only serializes home-made scripts, but still "batch
clashes" occur.

Proposed Fix:
I have done following changes and I'm using it for a year or so. Note that
the "original setup" represents woody.


/etc/crontab (snippet)::
# Original, commented out.
# m h dom mon dow user	command
#25 6 * * * root test -e /usr/sbin/anacron || run-parts --report /etc/cron.daily
#47 6 * * 7 root test -e /usr/sbin/anacron || run-parts --report /etc/cron.weekly
#52 6 1 * * root test -e /usr/sbin/anacron || run-parts --report /etc/cron.monthly
#
# Instead, following is put into service. Note that it starts just past
# midnight instead of 6:25. Also, while irrelevant, it is run independent
# of whether anacron is installed or not.
03 0  * * *   root    nice run-parts --report /etc/cron.daily


/etc/anacrontab (snippet)::
# Original, commented out. Change to anacrontab is of secondary nature.
# 1   5   cron.daily    nice run-parts --report /etc/cron.daily
# 7   10  cron.weekly   nice run-parts --report /etc/cron.weekly
# 30  15  cron.monthly  nice run-parts --report /etc/cron.monthly
#
# Only difference is an increase in the inactivity periods for weekly and
# monthly runs. This is because, since these batches don't start at a
# precisely predefined time anymore, it may cause race conditions with
# "just in time" inactivity periods. They were too tight anyway, and
# monthly inactivity period was incorrect even before this fix (as is in
# woody), because it kicks in incorrectly when a specific month has 31
# days.
1   5   cron.daily    nice run-parts --report /etc/cron.daily
8   10  cron.weekly   nice run-parts --report /etc/cron.weekly
32  15 cron.monthly   nice run-parts --report /etc/cron.monthly


ls -1 /etc/cron.daily/* ::
/etc/cron.daily/0anacron
...
... usual cron.daily scripts ...
...
/etc/cron.daily/zz1-weekly
/etc/cron.daily/zz2-monthly


/etc/cron.daily/zz1-weekly ::
#!/bin/sh
#
# Only runs on Sundays. (In place of the disabled /etc/crontab entry)
# Either
# [ `date +%w` -eq 0 ] && run-parts --report /etc/cron.weekly
# Or
[ `date +%u` -eq 7 ] && run-parts --report /etc/cron.weekly


/etc/cron.daily/zz2-monthly ::
#!/bin/sh
#
# Only runs on 1st of month. (In place of disabled /etc/crontab entry)
[ `date +%d` -eq 01 ] && run-parts --report /etc/cron.monthly


With these changes, now, daily maintenance starts at 00:03 past midnight,
followed by weekly (if appropriate), and then monthly (if appropriate).

So we can only know the exact time cron.daily starts, but we can't
successfully estimate when (at which hour) cron.weekly or cron.monthly
starts. That depends on how long previous batch(es) took to complete. So
we can't afford "just in time" anacron scheduling, because previous weekly
script might have been started at -say- 3:00 o'clock previous week, and if
cron.weekly is to be started at 4:00 o'clock this week (because e.g.
cron.daily took longer this time) anacron would incorrectly kick in
cron.weekly at 3:10, and this would mess up everything.

A change to anacrontab regarding cron.monthly was needed anyway, even
without this fix, because it was buggy, IMHO: It presumes all months are
30 days long. And it incorrectly kicks in on the last day of 31-day
months. So, cron.monthly incorrectly executes twice, once on the 31st of
the month and once more on the 1st of the new month.

So, in anacrontab, I have added one day (latency margin) to cron.weekly,
and two days (one to correct a bug, one for latency margin) to
cron.monthly.

I am using this setup for more than a year now, and I can confirm that it
works great. Any ideas appreciated.

And if this setup happens to be found correct, or gets corrected, I
propose adding this (or any other means of) serialization fix to
/etc/cron.{daily,weekly,monthly} batches.

-- 
Abdullah        | aramazan@ |
Ramazanoglu     | myrealbox |
________________| D.0.T cöm |__



Reply to: