Solved

Cron emulator/ faking cron

Posted on 2002-07-05
25
645 Views
Last Modified: 2010-05-18
Does anyone know a free script that will emulation the Unix cron utility.

I am not allowed to use cron to automate action every day have to be done automatically.

I would like it to use on a unix machine.

Can I use the sleep function?

Can someone help me to a script?
0
Comment
Question by:mmcw
  • 12
  • 8
  • 2
  • +2
25 Comments
 
LVL 84

Expert Comment

by:ozo
Comment Utility
use Schedule::Cron;
0
 

Author Comment

by:mmcw
Comment Utility
How to use that and where to find it?
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
0
 

Author Comment

by:mmcw
Comment Utility
Thank you for your answer.
But I can not use it because I am not allowed to install modules my self!

Isn't there way to use foreample the sleep command?
0
 

Author Comment

by:mmcw
Comment Utility
Ozo:
Is it save to use something like this
(found at: http://www.experts-exchange.com/questions/Q_20091375.html)

#############################################
#!/usr/bin/perl -w
print "Content-type: text/html\n\n";

use Socket;

while(1){
$content = get("http://www.my.url/file.csv") or die $!;
open (STOCK, "> /path/to/my/dir/stock.csv") or die "I don't wanna! \n";
print STOCK $content;
close (STOCK);
sleep(3*60*60);
}

sub get {
$url = shift;
$url =~ s|http://([^/:]+)(:(\d+))?||;
$remote = $1;
$port = $3 || 80;
$url or $url = "/";
$iaddr = inet_aton($remote) || return undef;
$paddr = sockaddr_in($port, $iaddr);
$proto = getprotobyname('tcp');
socket(SOCK, PF_INET, SOCK_STREAM, $proto)  || return undef;
connect(SOCK, $paddr) || return undef;
$old = select SOCK; $|++; select $old;
print SOCK "GET $url HTTP/1.1\r\nHost: $remote\r\n\r\n";
while (<SOCK>) {
   /Content-Length: (\d+)/ and $bytes = $1;
   if ($_ eq "\r\n") {
      <SOCK>;
      last;
   }
}
$bytes or return undef;
read SOCK ,$contents, $bytes;
close SOCK;
return $contents;
}
########################################

A sleep routine what will check a file for the word "off" to see if it has to continu.

Can this be used?
What about the processor time?
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
Looks like it should work on a unix system,
otherwise, you might have to use "\015\012" for "\r\n"
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
You should probably also close SOCK even when you return undef
0
 

Author Comment

by:mmcw
Comment Utility
Will I get problems with my provider about cpu and memory time running this script?
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
I don't know your providers policy about cpu and memory time, and I don't know how big http://www.my.url/file.csv is,
but "get"ing it once every 3 hours doesn't seem unreasonable to me.
0
 

Author Comment

by:mmcw
Comment Utility
When the script is in sleep it should be no problem for the provider? The script will then not use memory or cpu time?
0
 
LVL 84

Accepted Solution

by:
ozo earned 200 total points
Comment Utility
The script will continue to use memory, although it will probably get swapped out before long.
It will not use cpu time while sleeping
0
 

Author Comment

by:mmcw
Comment Utility
Or do you have a better idea without using extra (not standard) modules?
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:mmcw
Comment Utility
How to stop the sleep process?
Can I use the option (very creative) used at:
http://www.experts-exchange.com/questions/Q_20091375.html
0
 
LVL 3

Expert Comment

by:DVB
Comment Utility
(Wondering why he can't install modules in his home directory)
Use a signal to stop the sleep process.
$SIG{TERM}=&my_signal_handler();

sub my_signal_handler()
{
     (flush anything you want)
     close (all open files/handles);
     exit 0;
}

This will properly shutdown your process.

0
 

Author Comment

by:mmcw
Comment Utility
"(Wondering why he can't install modules in his home directory)"

How to install the module Schedule::Cron; in my home directory? I do not have root rights!

"Use a signal to stop the sleep process.
$SIG{TERM}=&my_signal_handler();

sub my_signal_handler()
{
    (flush anything you want)
    close (all open files/handles);
    exit 0;
}"

Could you help me implementing it into the code I gave in an earlier comment!

This will properly shutdown your process.
0
 
LVL 3

Expert Comment

by:DVB
Comment Utility
If you run perl -MCPAN -eshell, it will ask you lots of questions about where you want stuff installed.
Or you could just pass a parameter to the Makefile.PL telling it that you want installations to occur in your home directory. you should have full write permission in your home directory, that doesn't need root access.

And that sample code works as is.
You introduce a custom handler for SIGTERM with
$SIG{TERM}=&my_sig_handler;

#The signal handler
sub my_sig_handler()
{
     #This assumes stock was open.
     fflush(STOCK);
     close (STOCK);
     exit 0;
}

Hopefully, this gives you an idea of how to install a signal handler. I really really recommend getting the camel book, and the cookbook.
0
 
LVL 10

Expert Comment

by:oleber
Comment Utility
After having a problem like yours. My provider didn't let me use a cron and what I have to do didn't take long (just send some mail or preprocesse some pages that are slower).

I set the code necessary in a script that is usualy seen. That way the necessary code run and do the work. Like the code run less than 1% of the time that the scripts runs I dont have probleme whith my clients.

For resolving the problem of instaling modules, you can have modules isntalled in a directory that you control and set the code 'use lib("..\\modules");', for me works until now.

0
 

Expert Comment

by:weversbv
Comment Utility
After having a problem like yours. My provider didn't let me use a cron and what I have to do didn't take long (just send some mail or preprocesse some pages that are slower).

"I set the code necessary in a script that is usualy seen. That way the necessary code run and do the work. Like the code run less than 1% of the time that the scripts runs I dont have probleme whith my clients."

What script so you use???

"For resolving the problem of instaling modules, you can have modules isntalled in a directory that you control and set the code 'use lib("..\\modules");', for me works until now."

How to do that???
0
 

Author Comment

by:mmcw
Comment Utility
Weversbv is asking the same I want to know?

"I set the code necessary in a script that is usualy seen. That way the necessary code run and do the work. Like the code run less than 1% of the time that the scripts runs I dont have probleme whith my clients."

What script so you use???

"For resolving the problem of instaling modules, you can have modules isntalled in a directory that you control and set the code 'use lib("..\\modules");', for me works until now."

How to setup the Schedule::Cron module local???
0
 
LVL 10

Expert Comment

by:oleber
Comment Utility
What script so you use???
The banner page of the site. Can be slow, who cares. See http://www.oleber.com .

How to setup the Schedule::Cron module local???
I didn't use the Schedule::Cron, I did my code directly in the script. I use other modules like HTML::Modules, Net::SMTP, ... In this cases you just have to uncompact the content of the zip file and copy the files to the correct places in modules directory.

insted of using the crons, you can sink something like

if (time() % 1000 == 0)
{
  # do 1º work
}
if (time() % 1001 == 0)
{
  # do 2º work
}
if (time() % 1002 == 0)
{
  # do 3º work
}

its just one idea that can work.
0
 

Author Comment

by:mmcw
Comment Utility
OZO:

I did now install this module but do not know how to continu.

This is what I want:

I want to run every day at 08.00 the perl script: www.test.com/cgi-bin/test.pl?action=test

How to do that with the schedule::cron module.

I did read the documentation but I stiil do not kown what to do?

Could you tell me what line do I have to add to my script?
0
 

Author Comment

by:mmcw
Comment Utility
I have found on the internet the following code. I have edited it a bit to make it work like cron. It will check every minute the crontab file to see if something has to be executed. To stop it I have added the part where a file stop.txt will be checked. If the value in the file is off the process will stop.

This is my problem. When I start this script from my browser it seem to load for ever. The script runs in the background. When you push the stop button of the browser the cron.pl script keeps running. That is what I want, but is it possible to return only an message to the browsers screen that the perl script is started. Not the endless loading of the page!

#!/usr/local/bin/perl
#########################################################################
#                                                                                                            #
# subroutine cron -- perl implementation of cron                                    #
#                                                                                                            #
#########################################################################
# $silent to 1, means no output to screen.
# $log to 1, means keep a log file of activity.
# $logmsg to 1, means keep a log file of the messages.

$silent = 0;
$log = 1;
$logmsg = 1; # assign this only in emergency
$stopfile = "/home/cgi-bin/Shop/Div/stop.txt";
$logfile = "/home/cgi-bin/Shop/Log/cronlog.txt";
$errfile = "/home/cgi-bin/Shop/Log/errorlog.txt";

# Start cron
start_cron();

#########################################################################
#                                                                                                            #
# main program                                                                                          #
#                                                                                                            #
#########################################################################

sub start_cron {
      
      print "Content-type: text/html\n\n";

      # return and let child do the work
      if (fork) {
               exit;
      }
      
      unless ($silent) {
            # Print to screen
            print "Crontab: scheduled tasks [$$] started.<br>\n";
      }

      # check file for on-off switch
      CSF(1);
      
      if (defined $ARGV[0]) {
            LOG("ACT", "using $ARGV[0] as crontab file\n");
            $crontab = $ARGV[0];
      }
      else {
            LOG("ACT", "using default file crontab");
            $crontab = "/home/cgi-bin/Shop/Div/crontab";
      }

      while (1) {

            # check file for on-off switch
            CSF();

          # Sleep till next minute
            my $icur_secs = time();
          my $icur_mins = int ( $icur_secs / 60 );
          my $next_mins = $icur_mins + 1;
          my $next_secs = $next_mins * 60;
          my $sleep_secs = $next_secs - $icur_secs;
          sleep( $sleep_secs );

            # mon = 0..11 and wday = 0..6
            my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
            $mon++; # to get it to agree with the cron syntax
            $year = $year + 1900;

            # check crontab file
            open(F, "$crontab") or
              LOG("ERR", "$!: Can't open crontab file: $crontab") or
                  die "Can't open crontab; file $crontab: $!\n";
                  
                  $line = 0;

                  while (<F>) {
                        $line++;

                        if (/^$/) {
                              LOG("MSG", "blank line $line");
                              next;
                        }

                        if (/^#/) {
                              LOG("MSG", "comment on line $line");
                              next;
                        }

                        ($tmin, $thour, $tmday, $tmon, $twday, $tcommand) = split(/ +/, $_, 6);
                        # pull out commands with spaces
                        if (/\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(.+)$/) {
                              $tcommand = $1;
                        }

                        LOG("MSG", "it is now " . sprintf "%02d:%02d:%02d on %02d/%02d/%02d wday=%02d", $hour, $min, $sec, $mon, $mday, $year, $wday);
                        LOG("MSG", "should we do $thour:$tmin on $tmon/$tmday/--, wday=$twday?");

                        $do_it = 0; # assume don't do it until proven otherwise

                        # do it -- this month?
                        if ( ($tmon eq "*") || ($mon == $tmon) || &in_csl($mon, $tmon, '1', '12')) {
                              $do_it = 1;
                              LOG("MSG", "the month is valid");
                        }
                        else {
                              $do_it = 0;
                              LOG("MSG", "cron: the month is invalid");
                        }

                        # do it -- this day of the month?
                        if ( $do_it && ( ($tmday eq "*") || ($mday == $tmday) || &in_csl($mday, $tmday, '1', '31')) ) {
                              $do_it = 1;
                              LOG("MSG", "the day of month is valid");
                        }
                        else {
                              $do_it = 0;
                              LOG("MSG", "the day of month is invalid");
                        }

                        # do it -- this day of the week?
                        if ( $do_it && ( ($twday eq "*") || ($wday == $twday) || &in_csl($wday, $twday, '0', '6')) ) {
                              $do_it = 1;
                              LOG("MSG", "the day of week is valid");
                        }
                        else {
                              $do_it = 0;
                              LOG("MSG", "the day of week is invalid");
                        }

                        # do it -- this hour?
                        if ( $do_it && ( ($thour eq "*") || ($hour == $thour)|| &in_csl($hour, $thour, '0', '23') ) ) {
                              $do_it = 1;
                              LOG("MSG", "the hour is valid");
                        }
                        else {
                              $do_it = 0;
                              LOG("MSG", "the hour is invalid");
                        }

                        # do it -- this minute?
                        if ( $do_it && ( ($tmin eq "*") || ($min == $tmin) || &in_csl($min, $tmin, '0', '59') ) ) {
                              $do_it = 1;
                              LOG("MSG", "the min is valid");
                        }
                        else {
                              $do_it = 0;
                              LOG("MSG", "the minute is invalid");
                        }

                        # executing command
                        if ($do_it) {
                              chomp $tcommand;
      
                              if ($tcommand =~ /^http/) {
                                    LOG("ACT", "executing command <$tcommand> using LWP::simple");

                                    use LWP::Simple;
                                    getprint("$tcommand");
                              }
                              else {
                                    LOG("ACT", "executing command <$tcommand>");

                                    system ("$tcommand");
                              }
                        }
                  }

            close(F);
            LOG("MSG", "***-----***");
      }

      exit;
}

#########################################################################
#                                                                                                            #
# in_csl searches for an element in a comma separated list                        #
#                                                                                                            #
#########################################################################

sub in_csl {
      my ($what, $csl, $start, $end) = @_;
      
      # Local variables
      my (@a, @b);
      my ($i, $x);

      LOG("MSG", "Processing CSL");
      @a = split(/,/, $csl);
      @b = ();
      map {
            if (/^(\d+)\/(\d+)$/) {
                  if ($2 > 0 && $1 >= $start && $1 <= $end) {
                        for ($i = $1; $i <= $end; $i += $2) {
                              push(@b, $i);
                        }
                  }
            }
            elsif (/^\*\/(\d+)$/) {
                  if ($1 > 0) {
                        for ($i = $start; $i <= $end; $i += $1) {
                              push(@b, $i);
                        }
                  }
            }
            elsif (/^(\d+)-(\d+)\/(\d+)$/) {
                  if ($3 > 0) {
                        if ($1 <= $2) {
                              for ($i = $1; $i <= $2; $i += $3) {
                                    push(@b, $i);
                              }
                        }
                        else {
                              for ($i = $1; $i <= $2 + $end + (1 - $start); $i += $3) {
                                    if ($i <= $end) {
                            push(@b, $i);
                                    }
                                    else {
                                          push(@b, $i - $end - (1 - $start));
                                    }
                              }
                        }
                  }
            }
            elsif (/^(\d+)-(\d+)$/) {
                  if ($1 <= $2) {
                        for ($i = $1; $i <= $2; $i++) {
                              push(@b, $i);
                        }
                  }
                  else {
                        for ($i = $1; $i <= $2 + $end + (1 - $start); $i++) {
                              if ($i <= $end) {
                                    push(@b, $i);
                              }
                              else {
                                    push(@b, $i - $end - (1 - $start));
                              }
                        }
                  }
            }
            else {
                  push(@b, $_);
            }
      } @a;
   
      for $x (@b) {
        LOG("MSG", "is $what equal to item $x?");
        if ($what eq $x) {
            return 1;
        }
    }
   
      return 0;
}

#########################################################################
#                                                                                                            #
# Check for stopfile and/ or stop process                                                #
#                                                                                                            #
#########################################################################

sub CSF {
      
      my $sfc = shift;
      
      # check file for on-off switch
      open (DAT, "$stopfile") or
             LOG("ERR", "$!: Can't open stopfile file: $stopfile") or
            die "Can't open stopfile; file $stopfile: $!\n";

            my $state = <DAT>;
            if ($state =~ /off/i) {
                  if ($sfc) {
                        unless ($silent) {
                              # Print to screen
                              print "Crontab: scheduled tasks disabled.<br>\n";
                              print "Crontab: stop file = off.<br>\n";
                        }
                        
                        # Print to error log file
                        LOG("ERR", "tried to start disabled scheduled tasks - stop file = off");

                        exit();
                  }
                  else {
                        LOG("MSG", "scheduled tasks stopped");                        
                        # Stop scheduled tasks
                        die "Crontab: scheduled tasks stopped!\n";
                  }
            }
            
      close (DAT);
}

#########################################################################
#                                                                                                            #
# Log activity                                                                                          #
#                                                                                                            #
#########################################################################

sub LOG {

      my ($type, $message) = @_;

      my ($file, $header);
      if ($type eq "ACT") {
            return unless ($log);
            $file = $logfile;
            $header = "cron";
      }
      elsif ($type eq "MSG") {
            return unless ($logmsg);
            $file = $logfile;
            $header = "cron";            
      }
      elsif ($type eq "ERR") {
            $file = $errfile;
            $header = "cron error";      
      }
                  
      # mon = 0..11 and wday = 0..6
      my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
      $mon++; # to get it to agree with the cron syntax
      $year = $year + 1900;

      open(FILE,">>$file") or die "Can't open log file: $file: $!\n";
            printf FILE "$header*[%02d/%02d/%02d %02d:%02d:%02d]: $message\n",$mon,$mday,$year,$hour,$min,$sec;
      close(FILE);
}

1;
 
Can someone tell me how do that?
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
You could try backgrounding the program with:
    fork && exit;
0
 

Author Comment

by:mmcw
Comment Utility
Where to add those lines?
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
I'd say just before
# Start cron
start_cron();
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Suggested Solutions

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now