#!/usr/bin/perl -w use strict; use Data::Dumper; $|=1; =info Author : Sanjoga Sahu. Date of Modification : 03rd, Dec, 2010. (v1.0.0) Operating System(s) : Linux Description : Runs jobs line crontab. --------------------------------------------------------------------- Execution Method : Options: -h : Help -d : Debug Printing Mode -c : Config file to be used (No Space between the arguments) [Also Works with Options [config= | conf=] Ex: i. -c/abc/xyz/mycron.conf ii. conf=/abc/xyz/mycron.conf iii. config=/abc/xyz/mycron.conf Execution Method : 1) Running Script Normally (No debug Printing log)... nohup cron_own.pl & 2) Running Debug Printing Mode (Prints log)... nohup cron_own.pl -d >>! \$HOME/cron_own.log & 3) Running Script Normally using diffrent config file (No debug Printing log)... nohup cron_own.pl config=/abc/xyz/mycron.conf & --------------------------------------------------------------------- Config Information : Create a config file at : $HOME/config/cron_own.conf Config Entries are like contab... Example: Minute Hour Day of Month Month Day of Week Command (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat) 0 2 12 * 0,6 /usr/bin/find Example: (Run in every 00 min of an Hour) 00 * * * * $HOME/MirrorUp_genius_1.0.1.pl I=no >> $HOME/MirrorUp.out 2>&1 --------------------------------------------------------------------- How to check the process and stop script: #ps -elf | grep cron 0 S XXXXXXXX 27196 26725 0 78 0 - 5759 - 00:04 pts/2 00:00:00 /usr/bin/perl -w cron_own.pl #kill -9 27196 Will Display: [1] Killed cron_own.pl >> $HOME/cron_own.log --------------------------------------------------------------------- =cut my %INFO=(); my $config="$ENV{'HOME'}/config/cron_own.conf"; my $opt=lc(&trim($ARGV[0])); my $debug=0; my $c_flg=0; if(defined $opt) { foreach my $opt_e (@ARGV) { if($opt_e eq '-h') { &usage(0); exit(0); } if($opt_e eq '-d') { $debug=1; } if($opt_e=~ /(config=|conf=|-c)(\S+)/) { $config=$2; } if($opt_e=~ /-c|conf/) { $c_flg=1; } } } print "\n" if($debug==1); unless(-f $config) { print "\n[$0] Configuration File NOT Found, Please Create [$config]\n"; &usage(); exit(1); } if($c_flg) { print "[$0] Configuration File Used [$config]\n"; } my $run=1; #Infinite While loop which reads the config file in every minute and run them if the run conditions are met. while(1) { my $machine=&trim(`uname -n`); my $process=$$; my $TimeStamp=`date +[%Y-%m-%d' '%H:%M:%S`; chomp $TimeStamp; $TimeStamp .=" ~ $machine ~ Pid ~ $process]"; #commnet the below print if no log required... print "$TimeStamp $0 Run [$run]...\n" if($debug==1); print "$TimeStamp $0 Configuration File Used : $config\n" if($debug==1); %INFO=(); &parse_config(); my $min=&trim(`date +%M`); my $hour=&trim(`date +%H`); my $date_month=&trim(`date +%d`); my $month=&trim(`date +%m`); my $day=&trim(`date +%a`); $day=&map_day($day); foreach my $key_job (sort {$a<=>$b} keys %INFO) { my %RUN=(); my $c_min = $INFO{$key_job}{'MIN'}; my $c_hour= $INFO{$key_job}{'HOUR'}; my $c_date_month=$INFO{$key_job}{'DATE_MONTH'}; my $c_month=$INFO{$key_job}{'MONTH'}; my $c_day= $INFO{$key_job}{'DAY'}; my $c_command=$INFO{$key_job}{'COMMAND'}; # print "$TimeStamp Current Info : MIN:$min, HOUR:$hour, DATE:$date_month, MONTH:$month, DAY:$day\n"; # print "$TimeStamp Config Final : MIN:$c_min, HOUR:$c_hour, DATE:$c_date_month, MONTH:$c_month, DAY:$c_day, COMMAND:$c_command\n"; #Checking the Run condion of job &set_run_flg($c_min,$min,\%RUN); &set_run_flg($c_hour,$hour,\%RUN); &set_run_flg($c_date_month,$date_month,\%RUN); &set_run_flg($c_month,$month,\%RUN); &set_run_flg($c_day,$day,\%RUN); if(defined $RUN{0}) { #skipping the job if run condition is not met #commnet the below print if no log required... print "$TimeStamp Skipping : $c_command\n" if($debug==1); } else { #running the job when run condition is met my $child_pid; if (!defined($child_pid = fork())) { die "cannot fork: $!"; } elsif ($child_pid) { # I'm the parent #wait for child job to finish and kills process[“zombies”] wait; } else { # I'm the child #commnet the below print if no log required... print "$TimeStamp Fork Process Running : $c_command\n" if($debug==1); #runs the job in fork process ans exits once completed. system("nohup $c_command &"); #print "$TimeStamp Done Running : $c_command, exiting fork process...\n"; exit(0); } } #print "\n$TimeStamp NEXT JOB.....\n"; } #commnet the below print if no log required... print "$TimeStamp sleep 60...\n\n" if($debug==1); sleep 60; $run++; } ##################################################################### =head Checks the config [time] and current [time] and set the flags, whether the job to run or not =cut sub set_run_flg { my ($config_info,$current_info,$RUN)=@_; my $flg=0; my %CONFIG_INP=(); my @CONF=split(/\,/,$config_info); @CONF= map {trim($_)} @CONF; @CONF= map {$_=sprintf("%02s",$_);} @CONF; $current_info=sprintf("%02s",$current_info); map {$CONFIG_INP{$_}=1} @CONF; #print Dumper(\%CONFIG_INP); if($config_info eq '*') { $flg=1; } elsif(defined $CONFIG_INP{$current_info}) { $flg=1; } else { $flg=0; } #print "$config_info,$current_info--FLG:::$flg\n"; $$RUN{$flg}=$flg; return; } ##################################################################### =head Validates the configuration information. Minute Hour Day of Month Month Day of Week Command (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat) 0 2 12 * 0,6 /usr/bin/find =cut sub check_range { my ($config_info,$range,$line)=@_; my ($lower,$higher)=split(/-/,$range,2); $lower=sprintf("%02s",$lower); $higher=sprintf("%02s",$higher); my %flg=(); my @CONF=split(/\,/,$config_info); @CONF= map {trim($_)} @CONF; @CONF= map {$_=sprintf("%02s",$_);} @CONF; #print "$config_info,$range,$higher,$lower----$line---\n"; if($config_info eq '*') { $flg{1}=1; } elsif($config_info=~ /\,/) { map { if($_ >= $lower && $_ <= $higher){ $flg{1}=1; } else { $flg{0}=1; } }@CONF; } elsif($config_info >= $lower && $config_info <= $higher) { $flg{1}=1; } else { $flg{0}=1; } if(defined $flg{0}) { print "ERROR >> Incorrect Config Info [$config_info], Ex: [$range], $0 Line Number ",__LINE__, "\n"; print "LINE >>$line<<\n"; exit(1); } return; } ##################################################################### #Parse the config File and feeds %INFO hash sub parse_config { unless (-f $config) { print "The Cron Own Configuration file NOT Found : $config\n"; print "Exiting...\n"; exit(1); } open (RR,$config) || die "Couldn't Open for reading $config : $!\n"; my $count=1; #print "~~~~~~*****CONFIG PARSE START******~~~~~~\n"; foreach my $line () { $line=&trim($line); next if($line=~/^\#|^$/); my $TimeStamp=`date +[%Y-%m-%d' '%H:%M:%S]`; chomp $TimeStamp; $line=~ s/\s*\,\s*/,/g; #print "$TimeStamp Config Info : $line\n"; my ($min,$hr,$date_month,$month,$day_week,$command)=split(/\s+/,$line,6); $day_week=&map_day($day_week,$line); #print "---$month===\n"; $month=&map_month($month,$line); $min=sprintf("%02s",$min) if ($min ne '*'); $hr=sprintf("%02s",$hr) if ($hr ne '*'); $date_month=sprintf("%02s",$date_month) if ($date_month ne '*'); &check_range($min,"0-59",$line); &check_range($hr,"0-23",$line); &check_range($date_month,"1-31",$line); &check_range($month,"1-12",$line); &check_range($day_week,"0-6",$line); #print "Config Info#:#MIN:$min, HOUR:$hr, DATE:$date_month, MONTH:$month, DAY:$day_week, COMMAND:$command\n"; $INFO{$count}{'MIN'}=$min; $INFO{$count}{'HOUR'}=$hr; $INFO{$count}{'DATE_MONTH'}=$date_month; $INFO{$count}{'MONTH'}=$month; $INFO{$count}{'DAY'}=$day_week; $INFO{$count}{'COMMAND'}=$command; $count++; } #print "~~~~~~~~*****CONFIG PARSE DONE******~~~~~~~~\n\n"; return; } ##################################################################### =head Mapping of day run, returns numaric value or * depending upon the config inputs exits if invalid day =cut sub map_day { my ($day_inp,$line)=@_; my %MAP=( '*' => '*', '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', 'Sun' => '0', 'Mon' => '1', 'Tue' => '2', 'Wed' => '3', 'Thu' => '4', 'Fri' => '5', 'Sat' => '6', 'Su' => '0', 'Mo' => '1', 'Tu' => '2', 'We' => '3', 'Th' => '4', 'Fr' => '5', 'Sa' => '6' ); my @day=(); if($day_inp=~ /\,/) { my @DD=split(/\,/,$day_inp); foreach my $d (@DD) { my $dd=ucfirst($d); push(@day,$dd); } } else { my $dd=ucfirst($day_inp); push(@day,$dd); } my $day; foreach my $dd (@day) { if(defined $MAP{$dd}) { $day .="$MAP{$dd},"; } else { print "ERROR >> Invalid Day [$day_inp] Provided in config File : $config, $0 Line Number ",__LINE__, "\n"; print "LINE >>$line<<\n"; exit(1); } } chop $day; return $day; } ##################################################################### =head mapping of month retuns numeric value or * depending on the config info exits if invalid month =cut sub map_month { my ($month_inp,$line)=@_; #print "--$month_inp--==$line--\n"; my %MAP=( '*' => '*', '1' => '01', '2' => '02', '3' => '03', '4' => '04', '5' => '05', '6' => '06', '7' => '07', '8' => '08', '9' => '09', '01' => '01', '02' => '02', '03' => '03', '04' => '04', '05' => '05', '06' => '06', '07' => '07', '08' => '08', '09' => '09', '10' => '10', '11' => '11', '12' => '12', 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'Apr' => '4', 'May' => '5', 'Jun' => '6', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12', 'Ja' => '1', 'Fe' => '2', 'Ma' => '3', 'Ap' => '4', 'Ma' => '5', 'Ju' => '6', 'Ju' => '7', 'Au' => '8', 'Se' => '9', 'Oc' => '10', 'No' => '11', 'De' => '12' ); my $month=""; my @month=(); if($month_inp=~ /\,/) { my @mon=split(/\,/,$month_inp); foreach my $m (@mon) { my $mon=ucfirst($m); push(@month,$mon); } } else { my $mon=ucfirst($month_inp); push(@month,$mon); } foreach my $mon (@month) { if(defined $MAP{$mon}) { $month .="$MAP{$mon},"; } else { print "ERROR >> Invalid Month [$month_inp] Provided in config File : $config, $0 Line Number ",__LINE__, "\n"; print "LINE >>$line<<\n"; exit(1); } } chop $month; return $month; } ##################################################################### =head This Subroutine trims pre-post white Spaces/new line from the string Arguments: 1. $var (input String) =cut sub trim { my ($var)=@_; return unless (defined $var); $var=~s /^\s+|\s+$//g; return $var; } ##################################################################### sub usage { my $INFO=<>! \$HOME/cron_own.log & 3) Running Script Normally using diffrent config file (No debug Printing log)... nohup cron_own.pl config=/abc/xyz/mycron.conf & ***Configuration File Name : $config*** Note : If Configuration File is Not Available, then Create One with Above name. ################################################################################## #### #### ## Configuration Parameter Description : ## ## ## ## Minute Hour Day of Month Month Day of Week Command ## ## (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat) ## ## ## ## **************************************************************************** ## ## Example : (Run in every 00 min of an Hour) ## ## ## ## 00 * * * * /abspath/script_name >> /abspathlog/logname 2>&1 ## #### #### ################################################################################## EOD print "$INFO\n"; return; }