Is it possible to find all entries in a crontab that run between time X and time Y without having to parse the cron time entries myself? I'm mainly concerned with time hour and minute, not so much the other 3 time fields.
Anything is possible but you will have to parse crontab yourself.
There are no simple answers, but just because I can here's a partial solution in bash.
#!/bin/bash
start="${1-0:0}"
end="${2-0:0}"
start_hour=$(cut -d: -f1 <<<"$start")
end_hour=$(cut -d: -f1 <<<"$end")
start_min=$(cut -d: -f2 <<<"$start")
end_min=$(cut -d: -f2 <<<"$end")
# leading zeroes would be bad
let start_hour=10#${start_hour}
let end_hour=10#${end_hour}
let start_min=10#${start_min}
let end_min=10#${end_min}
cat /etc/crontab | \
grep -v ^\# | \
grep -E -v '^([a-zA-Z]+)' | \
awk '{print $1, $2, $7}' | \
while read line ; do
if [ ! -z "$line" ] ; then
h=$(cut -d' ' -f2 <<<"$line")
m=$(cut -d' ' -f1 <<<"$line")
cmd=$(cut -d' ' -f3- <<<"$line")
if [ "$h" = '*' ] || ( [ $h -ge $start_hour ] && [ $h -le $end_hour ] ) ; then
if [ "$m" = '*' ] || ( [ $m -ge $start_min ] && [ $m -le $end_min ] ) ; then
echo $cmd
fi
fi
fi
done
Call like
cron_between 09:00 16:59
This certainly won't work for complex time specifications (e.g. */2) and only reports on the first part of the command. All of this can be corrected, but probably you'd be better off doing it in perl or something.
Since this doesn't seem possible without parsing cron, I decided to write it myself in perl:
(not sure why the formatting is fubar)
#!/usr/bin/perl -w
use strict;
use Set::CrossProduct;
my $begin;
my $end;
if($ARGV[0] && $ARGV[0] =~ /before/i){
$begin = 0;
$end = $ARGV[1];
}
elsif($ARGV[0] && $ARGV[0] =~ /after/i){
$end = 2400;
$begin = $ARGV[1];
}
else{
$begin = $ARGV[0];
$end = $ARGV[1];
}
if(!defined($begin) || !defined($end)){
print STDERR "Invalid Arguments\n";
exit 1;
}
my @crontab = `crontab -l`;
foreach my $cronjob (@crontab){
chomp $cronjob;
next if $cronjob =~ /^ *\#/ ||$cronjob =~ /^ *$/ ;
#print "in: $cronjob\n";
my ($min,$hour,$day_of_month,$month,$day_of_week, @cmd) = split(/ /, $cronjob);
my @mins = expandRange($min,0,59);
my @hours = expandRange($hour,0,23);
my $cp = Set::CrossProduct->new([\@hours,\@mins]);
my $combos = $cp->combinations();
foreach my $time ( map { $_->[0]*100 + $_->[1] } @$combos){
if($time >= $begin && $time <= $end){
print $cronjob,"\n";
last; #don't print the job n times, just once
}
}
}
sub expandRange{
my ($in,$begin,$end) = @_;
#print "in: ($in)[$begin:$end]\n";
my @range;
my @vals = split(/,/,$in);
foreach my $val (@vals){
my $mult = 1;
if($val =~ /\/(.+)$/){
$mult = $1;
$val =~ s/\/(.+)//;
}
if($in =~ /\*/){
@range = grep { $_ % $mult == 0 && $_ >= $begin && $_ <= $end } $begin..$end;
}
elsif($val =~ /[\-:]/){
my ($first, $last) = split(/[\-:]/,$val);
push(@range, grep { $_ % $mult == 0 && $_ >= $begin && $_ <= $end } $first..$last);
}
elsif($val >= $begin && $val <= $end) {
push(@range, $val);
}
}
my %unique;
@unique{@range} = 1;
return sort keys %unique;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With