Thanks for everyone's input. A couple of the scripts gave me some good ideas, but I ended up rolling my own. It still needs a little tweaking, but here's what I have so far:
#!/usr/bin/perl -w
use strict;
sub cron_parse {
# This routine takes a time (seconds since epoch) and a crontab entry,
+ and returns
# the next time the process would kick off. Pass the script the last t
+ime a job ran,
# and the cron entry, and compare the result to the current date. This
+ will tell you
# if the job is overdue. The cron entry passed should contain only the
+ 5 schedule
# columns. Day-of-month and Month are ignored (my processes don't use
+them).
# If anything is wrong with the input, undef is returned.
my $last = shift || return undef;
my @last = localtime($last); # 1 - minutes, 2 - hours, 6 - day
+of week
$last = (1440 * $last[6]) + (60 * $last[2]) + $last[1];
$_ = shift || return undef;
my @cron_array = split;
return undef unless $#cron_array == 4;
my $minutes = &cron_range_populate (59, $cron_array[0]) || return
+undef;
my $hours = &cron_range_populate (23, $cron_array[1]) || return
+undef;
my $days = &cron_range_populate ( 6, $cron_array[4]) || return
+undef;
# In theory, I should now have three array references that pass al
+l checks
for my $day (@$days) { for my $hour (@$hours) { for my $minute (@$
+minutes) {
if ( (1440 * $day) + (60 * $hour) + $minute >= $last) {
return ( "Day $day, Hour $hour, Minute $minute" );
}
} } }
return ( "Day $$days[0], Hour $$hours[0], Minute $$minutes[0]" );
}
sub cron_range_populate {
my ($max, $range) = @_;
my @range = ();
if ($range eq '*') { return \@{[0..$max]}; }
elsif ($range !~ /[-,]/) { push @range, $range; }
else {
my @mini = split /,/, $range;
for (@mini) {
return undef if /-.*-/; # 1 dash per subsection, e.g.,
+"2-6-9, 24" is invalid
if ( !/-/ ) { push @range, $_; }
else {
return undef unless /(\d+)-(\d+)/;
return undef unless $1 < $2;
push @range, ($1..$2);
}
}
}
return undef if $#range == -1;
for (@range) { return undef unless ($_ >= 0 && $_ <= $max); }
return \@range;
}
my $next_job = &cron_parse(time, '04 13-16 * * 01,02,03,04,05') || "ba
+d input";
print "Next job kicks off : $next_job\n";
Comments welcome. |