#!/usr/local/bin/perl ########################################################################## # # scheduled.pl # # reads the crontab for the current user and provides a listing # of what's scheduled to run today, or on a specified date # # Note: using a date parameter might not work correctly on an x86 machine ########################################################################## use strict; use Time::Local; use POSIX; my $currentuser = $ENV{LOGNAME}; my $parameter = $ARGV[0]; if ($parameter eq '-h') {usage();} if ($parameter ne '') { if ($parameter !~ /^\d{4}\/\d{2}\/\d{2}$/) { print "\nBad date parameter - please supply in the form of MMMM/DD/YY\n\n"; exit(-1); } } my ($sorthour, $sortmin, $cronline, $today, $tday, $tmonth); my (@sortlines, @sortedlines, @taskpieces); my @lines = (); my @cronlines = `crontab -l`; my $todayword = "today "; my $firstone = 1; my $oldhour = '99'; ### "create" today's date my ($sec, $min, $hour, $inday, $inmonth, $year, $inwday, $yday, $isdst) = localtime; $inmonth++; $today = sprintf ("%4.4d/%2.2d/%2.2d", $year+1900, $inmonth, $inday); if ($parameter ne '') { $today = $parameter; $todayword = ''; $year = substr($today, 0, 4); $inmonth = substr($today, 5, 2); $inday = substr($today, 8, 2); # "catalytic" conversion to get the day of the week my $time = timelocal('10','10','10', $inday, $inmonth-1, $year); ($sec, $min, $hour, $inday, $inmonth, $year, $inwday) = localtime($time); $inmonth++; } if (length($inmonth) == 1) {$inmonth = sprintf("%2.2d", $inmonth);} if (length($inday) == 1) {$inday = sprintf("%2.2d", $inday);} if (length($inwday) == 1) {$inwday = sprintf("%2.2d", $inwday);} my $headerline = "\nScheduled to run $todayword($today) as user <<$currentuser>>:\n\n"; # get relevant schedule lines from crontab foreach my $line (@cronlines) { chomp $line; if ($line !~ /^#/) {push @lines, $line;} } # process the relevant crontab lines foreach my $line (@lines) { my ($cmin, $chour, $cday, $cmonth, $cwday, @taskpieces) = split ' ', $line; my ($daymatch, $monthmatch); $daymatch = $monthmatch = 0; # if it absolutely runs every day, we want it if (($cday eq '*') and ($cwday eq '*')) {$daymatch = 1; $monthmatch = 1;} else { # if any day of the month, check specific day of the week if ($cday eq '*') { if (length($cwday) == 1) {$tday = sprintf("%2.2d", $cwday);} if ($tday eq $inwday) {$daymatch = 1;} elsif ($cwday =~ /,/) {$daymatch = docommacheck($cwday, $inwday);} elsif ($cwday =~ /-/) {$daymatch = dodashcheck($cwday, $inwday);} } else # if any day of the week, check specific day of the month { if (length($cday) == 1) {$tday = sprintf("%2.2d", $cday);} if ($tday eq $inday) {$daymatch = 1;} elsif ($cday =~ /,/) {$daymatch = docommacheck($cday, $inday);} elsif ($cday =~ /-/) {$daymatch = dodashcheck($cday, $inday);} } # check the month if (($cmonth eq "*") or ($cmonth eq $inmonth)) {$monthmatch = 1;} else { if (length($cmonth) == 1) {$tmonth = sprintf("%2.2d", $cmonth);} if ($tmonth eq $inmonth) {$monthmatch = 1;} if ($cmonth =~ /,/) {$monthmatch = docommacheck($cmonth, $inmonth);} elsif ($cmonth =~ /-/) {$monthmatch = dodashcheck($cmonth, $inmonth);} } } # if it runs today, store for output if ($monthmatch and $daymatch) { $sorthour = prepforsort($chour); $sortmin = prepforsort($cmin); push @sortlines, "$sorthour`$sortmin`$line"; } } # sort implicitly by time and output the jobs @sortedlines = sort{$a cmp $b} @sortlines; foreach my $templine (@sortedlines) { (undef, undef, $cronline) = split '`', $templine; my ($cmin, $chour, $cday, $cmonth, $cwday, @taskpieces) = split ' ', $cronline; if ($firstone) {print $headerline;} $chour = expand($chour); $cmin = expand($cmin); # put a blank line between different hours and output the data if (($chour ne $oldhour) and ($oldhour ne '99') and (!$firstone)) {print "\n";} print "Hour:$chour Min:$cmin \n "; foreach my $task (@taskpieces) {print "$task ";} print "\n"; $oldhour = $chour; $firstone = 0; } sub docommacheck() # check each element of a "comma" list { my ($specword, $checkthis) = @_; my ($spec, $specmatch, @speclist); $specmatch = 0; @speclist = split ',', $specword; foreach $spec (@speclist) {if (length($spec) == 1) {$spec = sprintf("%2.2d", $spec);}} foreach $spec (@speclist) {if ($spec == $checkthis) {$specmatch = 1;}} return $specmatch; } sub dodashcheck() # check each element of a "dash" list { my ($specword, $checkthis) = @_; my ($spec, $specmatch, @speclist); $specmatch = 0; @speclist = split '-', $specword; for (my $idx=$speclist[0]; $idx<=$speclist[1]; $idx++) { $spec = sprintf("%2.2d", $idx); if ($spec == $checkthis) {$specmatch = 1;} } return $specmatch; } sub expand() # expand the data if it's a dash list, i.e., 7-12 becomes 7,8,9,10,11,12 # also expand all parameters to two digits, i.e., 7 becomes 07. # done for consistent output { my ($inlist) = @_; my @list; my $outlist = ''; if ($inlist =~ /,/) { @list = split ',', $inlist; foreach my $piece (@list) {if (length($piece) == 1) {$piece = sprintf("%2.2d", $piece);}} $outlist = join ',', @list; } elsif ($inlist =~ /-/) { @list = split '-', $inlist; for (my $idx=$list[0]; $idx<=$list[1]; $idx++) {$outlist .= sprintf("%2.2d,", $idx);} chop($outlist); } else { if ((length($inlist) == 1) and ($inlist ne "*")) {$inlist = sprintf("%2.2d", $inlist);} $outlist = $inlist; } return $outlist; } sub prepforsort() # create normalized hour and minute for output sorting { my ($rawvar) = @_; if (length($rawvar) == 1) {$rawvar = sprintf("%2.2d", $rawvar);} elsif ((substr($rawvar,0,1) =~ /^\d+$/) and (substr($rawvar,1,1) !~ /^\d+$/)) {$rawvar = sprintf("%2.2d", $rawvar);}; $rawvar = sprintf("%-100.100s", $rawvar); return $rawvar; } sub usage() { printf ("\nUsage: scheduled.pl [ (no parameter) | -h | mmmm/dd/yy ]\n"); printf (" Indicates what's scheduled to run today as user <$currentuser>.\n"); printf (" This is the normal behavior when no parameter is supplied.\n"); printf (" program -h displays this text.\n"); printf (" Supplying a date in the specified format will run this program\n"); printf (" for that date. In that case, the results can NOT be assumed\n"); printf (" to be reliable, as the contents of the crontab file may \n"); printf (" or different on that date.\n\n"); exit(0); }