代码之家  ›  专栏  ›  技术社区  ›  frankc

查找在给定时间之间运行的cron作业

  •  1
  • frankc  · 技术社区  · 14 年前

    是否可以在crontab中找到在时间X和时间Y之间运行的所有条目,而不必自己分析cron time条目?我主要关心的是时间-小时和分钟,而不是其他3个时间域。

    4 回复  |  直到 14 年前
        1
  •  3
  •   sorpigal    14 年前

    任何事情都有可能,但是您必须自己解析crontab。

    这里没有简单的答案,但只是因为我可以在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
    

    像打电话一样

    cron_between 09:00 16:59
    

        2
  •  2
  •   frankc    14 年前

    因为不解析cron这似乎是不可能的,所以我决定自己用perl编写它:
    (不确定格式为何为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;
    

    }

        3
  •  1
  •   Scott Harwell    14 年前

    您可以将crontab文件复制并粘贴到Excel中,然后创建几个这样做的函数。由于时间字段总是在同一个位置,Excel中的列将与执行该命令的时间范围相对应。

    您必须编写公式,这样就可以考虑单个整数值和重复值(比如10对*/10)。

    如果crobtab文件变化很大,并且有很多条目,那么您可以编写一个php脚本来非常快速地解析这些信息。

        4
  •  1
  •   nohat    12 年前

    你可以使用 Ruby 1.8.7 gem "crontab-parser" should_run? 在每个crontab条目上:

    require 'rubygems'
    require 'crontab-parser'
    
    start_time = Time.parse(ARGV[0])
    end_time   = Time.parse(ARGV[1])
    
    # CrontabParser barfs on env variable setting in a crontab, so just skip them
    cron_data = File.readlines(ARGV[2]).select {|line| line =~ /^[0-9*]/}
    cron  = CrontabParser.new(cron_data.join("\n"))
    (start_time..end_time).each do |timestamp|
      next unless timestamp.sec.to_i == 0
      cron.each do |cron_entry|
        if cron_entry.should_run?(timestamp)
          puts "#{timestamp}\t#{cron_entry.cmd}"
        end
      end
    end
    

    所以,如果你有 crontab.txt 看起来是这样的:

    *   *   *   *   *   foo
    18  15  *   *   *   bar
    

    date 或类似文件,包含crontab:

    ruby cron_report.rb "Sat Mar 3 02:07:32 UTC 2012" "Sat Mar 3 02:21:32 UTC 2012" crontab.txt
    

    Sat Mar 03 15:17:00 UTC 2012    *   *   *   *   *   foo
    Sat Mar 03 15:18:00 UTC 2012    *   *   *   *   *   foo
    Sat Mar 03 15:18:00 UTC 2012    18  15  *   *   *   bar
    Sat Mar 03 15:19:00 UTC 2012    *   *   *   *   *   foo
    Sat Mar 03 15:20:00 UTC 2012    *   *   *   *   *   foo