User Tools

Site Tools


Minimal perl cron-like scheduler

I used seconds for a better view. And to shorten a test time. =)

scheduler.pl
#!/usr/bin/env perl
 
use POSIX qw(tzset tzname strftime);
use Mojo::Util qw(dumper);
 
$ENV{TZ} = 'Europe/Moscow';
tzset;
 
sub expand {
    my ($def, $limit, $start) = @_;
    $limit = 100 unless defined $limit;
    $start = 1 unless defined $start;
    my @list = split ',', $def;
    my @out;
    my %n;
    foreach my $sub (@list) {
        if (my ($num) = $sub =~ m/^(\d+)$/ ) {
                next if $num < $start;
                next if $num > $limit;
                push @out, $num unless $n{$num};
                $n{$num} = 1;
        }
        elsif (my ($begin, $end) = $sub =~ /^(\d+)[-. ]+(\d+)$/) {
            foreach my $num ($begin..$end) {
                next if $num < $start;
                next if $num > $limit;
                push @out, $num unless $n{$num};
                $n{$num} = 1;
            }
        }
        elsif (my ($inc) = $sub =~ /^[*]\/(\d+)$/) {
            my $num = $start;
            while ($num <= $limit) {
                next if $num < $start;
                push @out, $num unless $n{$num};
                $num += $inc;
            }
        }
        elsif ($sub =~ /^[*]$/) {
            my $num = $start;
            my $inc = 1;
            while ($num <= $limit) {
                next if $num < $start;
                next if $num > $limit;
                push @out, $num unless $n{$num};
                $num += $inc;
            }
        }
    }
    @out = sort { $a <=> $b } @out;
    return \@out
}
 
sub compact {
    my $list = shift;
    my %n;
    my $out;
    foreach my $num (@{$list}) { $n{$num} = 1; }
    foreach my $num (sort { $a <=> $b } (keys %n)) {
        $out .= $num."-" if $n{$num+1} && not $n{$num-1};
        $out .= $num."," unless $n{$num+1};
    }
    $out =~ s/,$//;
    return $out;
}
 
sub match {
    my ($num, $list) = @_;
    foreach my $elem (@{$list}) {
        return 1 if $num == $elem;
    }
    return undef;
}
 
#my $list = "9-11,4,12,*/3";
#print $list."\n";
#my $expanded = expand($list);
#my $compacted = compact($expanded);
#print "$compacted\n";
 
### mdays, wdays, $hours, $mins
my $cronrec = "1-31 1-7 0-28 * 0-8,*/10,42-47,*/16";
my ($mdays, $wdays, $hours, $mins, $secs) = split '[ ;]', $cronrec;
 
print "mdays=".compact(expand $mdays, 31)."\n";
print "wdays=".compact(expand $wdays, 7)."\n";
print "hours=".compact(expand $hours, 23, 0)."\n";
print "mins=".compact(expand $mdays, 59, 0)."\n";
print "secs=".compact(expand $secs, 59, 0)."\n";
 
while (sleep 1) {
    my ($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime(time);
    $mon++; # 1..12 - Jan..Dec
    $wday = 7 if $wday == 0; # 1..7 -- Mon..Sun
    $year += 1900;
 
    if (match($mday, expand ($mdays,31))
        && match($wday, expand ($wdays,7))
        && match($hour, expand ($hours, 23, 0))
        && match($min, expand ($mins, 59, 0))
        && match($sec, expand ($secs, 59, 0))) {
                print "match -- mday=$mday wday=$wday $hour:$min:$sec\n";
    }
#    ($sec,$min) = localtime(time);
#    sleep (59-$sec);
}
#EOF

Output

# ./scheduler.pl
mdays=1-31
wdays=1-7
hours=0-23
mins=1-31
secs=0-8,10,16,20,30,32,40,42-48,50
match -- mday=2 wday=4 7:35:0
match -- mday=2 wday=4 7:35:1
match -- mday=2 wday=4 7:35:2
match -- mday=2 wday=4 7:35:3
match -- mday=2 wday=4 7:35:4
match -- mday=2 wday=4 7:35:5
match -- mday=2 wday=4 7:35:6
match -- mday=2 wday=4 7:35:7
match -- mday=2 wday=4 7:35:8
match -- mday=2 wday=4 7:35:10
match -- mday=2 wday=4 7:35:16
match -- mday=2 wday=4 7:35:20
match -- mday=2 wday=4 7:35:30
match -- mday=2 wday=4 7:35:32
match -- mday=2 wday=4 7:35:40
match -- mday=2 wday=4 7:35:42
match -- mday=2 wday=4 7:35:43
match -- mday=2 wday=4 7:35:44
match -- mday=2 wday=4 7:35:45
match -- mday=2 wday=4 7:35:46
match -- mday=2 wday=4 7:35:47
match -- mday=2 wday=4 7:35:48
match -- mday=2 wday=4 7:35:50
match -- mday=2 wday=4 7:36:0
match -- mday=2 wday=4 7:36:1
match -- mday=2 wday=4 7:36:2
match -- mday=2 wday=4 7:36:3
match -- mday=2 wday=4 7:36:4
...

First PagePrevious PageBack to overviewNext PageLast Page