tags:

views:

182

answers:

3

Are there any tools or reports out there that given a crontab file can output which jobs run within a specified time-frame.

Our crontab file has become very large and our system administrators struggle to find out which jobs need to be rerun when we have scheduled downtime on the server. We're trying to figure out which jobs we need to run.

I was planning on writing my own script but wondering if there was something out there already

+1  A: 

One thing you can do is:

  • Get Perl module Schedule::Cron

  • Modify it to sleep only optionally (create "fast-forward" mode and where it does sleep($sleep) change to do nothing when fast-forwarding. This will also require changing $now = time; call to do $now++.

  • Modify it to be able indicate start and end times for emulation.

  • Create a Perl one-liner which takes the output of crontab -l and converts it into similar contab but one which replaces command cmd1 arg1 arg2 with a perl subroutine sub { print "Execution: cmd1 arg1 arg2\n"}

  • Run the scheduler in the fast-forward mode, as indicated in the POD.

    It will read in your modified crontab, and emulate the execution.

DVK
NOTE: Roland (the author/maintainer of Schedule::Cron) posted a more elegant way of doing fast-forward using his module.
DVK
A: 

Here's a similar approach to DVK's but using Perl module Schedule::Cron::Events.

This is very much a "caveat user" posting - a starting point. Given this crontab file a_crontab.txt:

59 21 * * 1-5    ls >> $HOME/work/stack_overflow/cron_ls.txt
    # A comment
18 09 * * 1-5    echo "wibble"

The below script cron.pl, run as follows, gives:

$ perl cron.pl a_crontab.txt "2009/11/09 00:00:00" "2009/11/12 00:00:00"
2009/11/09 09:18:00 "echo "wibble""
2009/11/09 21:59:00 "ls >> $HOME/work/stack_overflow/cron_ls.txt"
2009/11/10 09:18:00 "echo "wibble""
2009/11/10 21:59:00 "ls >> $HOME/work/stack_overflow/cron_ls.txt"
2009/11/11 09:18:00 "echo "wibble""
2009/11/11 21:59:00 "ls >> $HOME/work/stack_overflow/cron_ls.txt"
2009/11/12 09:18:00 "echo "wibble""
2009/11/12 21:59:00 "ls >> $HOME/work/stack_overflow/cron_ls.txt"

Prototype (!) script:

use strict;
use warnings;

use Schedule::Cron::Events;

my $crontab_file = shift || die "! Must provide crontab file name";
my $start_time   = shift || die "! Must provide start time YYYY/MM/DD HH:MM:SS";
my $stop_time    = shift || die "! Must provide stop time YYYY/MM/DD HH:MM:SS";

open my $fh, '<', $crontab_file or die "! Could not open file $crontab_file for reading: $!";
my $table = [];
while ( <$fh> ) { 
    next if /^\s*$/;
    next if /^\s*#/;

    chomp;

    push @$table, new Schedule::Cron::Events( $_, Date => [ smhdmy_from_iso( $start_time ) ] );
}
close $fh;

my $events = [];
for my $cron ( @$table ) {
    my $event_time = $stop_time;
    while ( $event_time le $stop_time ) {
        my ( $sec, $min, $hour, $day, $month, $year ) = $cron->nextEvent;
        $event_time = sprintf q{%4d/%02d/%02d %02d:%02d:%02d}, 1900 + $year, 1 + $month, $day, $hour, $min, $sec;

        push @$events, qq{$event_time "} . $cron->commandLine . q{"};
    }
}

print join( qq{\n}, sort @$events ) . qq{\n};

sub smhdmy_from_iso {
    my $input = shift;

    my ( $y, $m, $d, $H, $M, $S ) = ( $input =~ m=(\d{4})/(\d\d)/(\d\d) (\d\d):(\d\d):(\d\d)= );

     ( $S, $M, $H, $d, --$m, $y - 1900 );
}

Hope you can adapt to your needs.

martin clayton
+1  A: 

There is a fine and clean solution for a 'simulation mode' of Schedule::Cron (and for any other module using sleep,time,alarm internally without modifying Schedule::Cron itself. You can use Time::Mock for throtteling, e.g. with

perl -MTime::Mock=throttle,600 schedule.pl

one can speedup your 'time machine' by a factor 600 (so, instead of sleeping for 10 minutes it will only sleep a second). Please refer to the manpage of Time::Mock for more details.

For using a crontab file directly with Schedule::Cron you should be able to take the example from the README directly:

 use Schedule::Cron;
 my $cron = new Schedule::Cron(sub { system(shift) },
                               file => "/var/spool/crontab.perl");
 $cron->run();

The trick here is to use a default dispatcher method which calls system() with the stored parameters. Please let me know, whether this will work for you or whether it will need to be fixed. Instead of system, you could use print as well, of course.

Roland Huß