Link to home
Start Free TrialLog in
Avatar of mmcw
mmcw

asked on

Cron emulator/ faking cron

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?
Avatar of ozo
ozo
Flag of United States of America image

use Schedule::Cron;
Avatar of mmcw
mmcw

ASKER

How to use that and where to find it?
Avatar of mmcw

ASKER

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?
Avatar of mmcw

ASKER

Ozo:
Is it save to use something like this
(found at: https://www.experts-exchange.com/questions/20091375/No-cron-access.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?
Looks like it should work on a unix system,
otherwise, you might have to use "\015\012" for "\r\n"
You should probably also close SOCK even when you return undef
Avatar of mmcw

ASKER

Will I get problems with my provider about cpu and memory time running this script?
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.
Avatar of mmcw

ASKER

When the script is in sleep it should be no problem for the provider? The script will then not use memory or cpu time?
ASKER CERTIFIED SOLUTION
Avatar of ozo
ozo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mmcw

ASKER

Or do you have a better idea without using extra (not standard) modules?
Avatar of mmcw

ASKER

How to stop the sleep process?
Can I use the option (very creative) used at:
https://www.experts-exchange.com/questions/20091375/No-cron-access.html
(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.

Avatar of mmcw

ASKER

"(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.
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.
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.

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???
Avatar of mmcw

ASKER

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???
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.
Avatar of mmcw

ASKER

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?
Avatar of mmcw

ASKER

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?
You could try backgrounding the program with:
    fork && exit;
Avatar of mmcw

ASKER

Where to add those lines?
I'd say just before
# Start cron
start_cron();