Wednesday Feb 14, 2007

Testing timezone enabled cron

My proof of concept for cron to understand timezones has moved to being closer to production code and I'm in the process of trying to get it put back in to Solaris. The biggest sticking point at the moment appears to be that the UNIX standards all say you can't do this in a crontab file.

Meanwhile following Adam's point that it's tested or it's broken I have started work on a test suite to test the new functionality in the blind optimism that a way around the standards can be found.

First I wrote a script that understands the five time fields used by cron and a timezone and can tell you if it is running when it should not. It is called crontest and can be run from cron like this:

15,45 \* 1-18,20 2 \* exec lang/sh/crontest 15,45 \\\* 1-18,20 2 \\\* Africa/Addis_Ababa

When it thinks things have gone wrong it prints an error with the process id and the parent process id so that it can be tied back to the entry in /var/cron/log.


Now I just need a crontab file that contains all the possible cron entries. Hmm that is not so easy. However if I can fill the crontab file with random entries I should get good coverage. So I have another script, crontab_create which generates random, but legal, crontab entries which call the crontest script. So I end up with a crontab that looks like this:


TZ=Asia/Tbilisi
42,50 0 1-25,27-28,30 1 \* exec lang/sh/crontest 42,50 0 1-25,27-28,30 1 \\\* Asia/Tbilisi
37,45 0-21,23 1-20,22-23,25 \* \* exec lang/sh/crontest 37,45 0-21,23 1-20,22-23,25 \\\* \\\* Asia/Tbilisi
32,40 0-16,18-19,21 \* 1 \* exec lang/sh/crontest 32,40 0-16,18-19,21 \\\* 1 \\\* Asia/Tbilisi
27,35 \* 1-10,12-13,15-21,23 1-11 \* exec lang/sh/crontest 27,35 \\\* 1-10,12-13,15-21,23 1-11 \\\* Asia/Tbilisi
22,30,57,59 0-6,8-9,11-17,19 1-5,7-8,10-16,18-28,30 1-6,8-9,11 \* exec lang/sh/crontest 22,30,57,59 0-6,8-9,11-17,19 1-5,7-8,10-16,18-28,30 1-6,8-9,11 \\\* Asia/Tbilisi
TZ=Asia/Tehran
17,25,52,54-56 0-1,3-4,6-12,14 2-3,5-11,13-23,25 1,3-4,6 \* exec lang/sh/crontest 17,25,52,54-56 0-1,3-4,6-12,14 2-3,5-11,13-23,25 1,3-4,6 \\\* Asia/Tehran
12,20,47,49-51 1-7,9-19,21 \* \* \* exec lang/sh/crontest 12,20,47,49-51 1-7,9-19,21 \\\* \\\* \\\* Asia/Tehran
7,15,42,44-46 0-2,4-14,16 1,3-13,15-22,24,26-27,29 1-2,4 \* exec lang/sh/crontest 7,15,42,44-46 0-2,4-14,16 1,3-13,15-22,24,26-27,29 1-2,4 \\\* Asia/Tehran
2,10,37,39-41 0-9,11-18,20,22 1-8,10-17,19,21-22,24 1-9,11 \* exec lang/sh/crontest 2,10,37,39-41 0-9,11-18,20,22 1-8,10-17,19,21-22,24 1-9,11 \\\* Asia/Tehran
5,32,34-36 0-4,6-13,15,17-18,20 1-3,5-12,14,16-17,19 1-4,6 \* exec lang/sh/crontest 5,32,34-36 0-4,6-13,15,17-18,20 1-3,5-12,14,16-17,19 1-4,6 \\\* Asia/Tehran
TZ=Asia/Thimphu
0,27,29-31 1-8,10,12-13,15 1-7,9,11-12,14 \* \* exec lang/sh/crontest 0,27,29-31 1-8,10,12-13,15 1-7,9,11-12,14 \\\* \\\* Asia/Thimphu
22,24-26 \* 1-2,4,6-7,9 1-3,5,7-8,10 \* exec lang/sh/crontest 22,24-26 \\\* 1-2,4,6-7,9 1-3,5,7-8,10 \\\* Asia/Thimphu
17,19-21 0,2-3,5 1-2,4-26,28-30 2-3,5 \* exec lang/sh/crontest 17,19-21 0,2-3,5 1-2,4-26,28-30 2-3,5 \\\* Asia/Thimphu
12,14-16 0-22 \* \* \* exec lang/sh/crontest 12,14-16 0-22 \\\* \\\* \\\* Asia/Thimphu
7,9-11 \* 1-16,18-20,22 1 \* exec lang/sh/crontest 7,9-11 \\\* 1-16,18-20,22 1 \\\* Asia/Thimphu
TZ=Asia/Tokyo
2,4-6,56,59 0-12,14-16,18 1-11,13-15,17 1 \* exec lang/sh/crontest 2,4-6,56,59 0-12,14-16,18 1-11,13-15,17 1 \\\* Asia/Tokyo
0-1,51,54 0-7,9-11,13 1-6,8-10,12 1-7,9-11 \* exec lang/sh/crontest 0-1,51,54 0-7,9-11,13 1-6,8-10,12 1-7,9-11 \\\* Asia/Tokyo
46,49,55 0-2,4-6,8 1,3-5,7 1-2,4-6,8 \* exec lang/sh/crontest 46,49,55 0-2,4-6,8 1,3-5,7 1-2,4-6,8 \\\* Asia/Tokyo
41,44,50 0-1,3 2 1,3 \* exec lang/sh/crontest 41,44,50 0-1,3 2 1,3 \\\* Asia/Tokyo
36,39,45 0 1 \* \* exec lang/sh/crontest 36,39,45 0 1 \\\* \\\* Asia/Tokyo
TZ=Asia/Ulaanbaatar

I needed some tuning so it would not be starting more than 100 jobs in anyone minute or at least it would not every minute as cron would then delay some jobs which in turn throws up false positives. I now have it with 551 timezones and 2756 cron entries which. There is probably (certainly) an optimization on the script to generate the cron entries so that they only run in the current month or at least for the likely length of the test.


It has been running for 24 hours on my home server. I can see the entries run from the log and I've not had any email telling me things have been submitted at the wrong time. So I am reasonably happy. Just to prove that it does what I think it does I added a line were the arguments to the script did not match the time specification of an entry that is running. Sure enough I get email (the crontab entry I changed the 25 minute to 50):


Your "cron" job on pearson
exec lang/sh/crontest 23,25 0-11,13-18,20 1-10,12-17,19 \\\* \\\* GMT

produced the following output:

17182:24396: Bad min: Should be 23,25 is 50:

This covers the easy cases to test that jobs that run run at the correct time. The harder part is to verify that every job that should run does run. Need to think that one through.

About

This is the old blog of Chris Gerhard. It has mostly moved to http://chrisgerhard.wordpress.com

Search

Archives
« April 2014
MonTueWedThuFriSatSun
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today