Friday, October 29, 2010

hacky crontab replacement in perl

I love system admins. I have been one my self. All that power at the tips of my fingers, and a manager with a big club behind me, waiting to play wack a mole with my fingers if i mees up. Of course system admins can tell a coder that he doesn't have access to cron.... but guess what: cron was written by programmers soo.... hack yourself up a 30 min crontab system in perl and chuckle in your sleep.

Heres my hacked up mess for the day.

#!/usr/bin/env perl

use strict;
use Date::Manip;

#For the valid formats look at 
#http://search.cpan.org/~muir/Time-modules-2003.0211/lib/Time/ParseDate.pm

my $period = 10;
my @tasks = (
             { time => "09:00:00", label => "morning", cmd  => "echo 'good morning'"},
             { time => "01:34:00", label => "Hi", cmd  => "echo 'good morning'"},
             { step => "+ 1 minutes", label => "5 mins", cmd  => "echo '5 mins'"},
             { step => "+ 10 seconds", label => "10 seconsd", cmd  => "echo '5 mins'"}
             
             );

sub string2date
{
    my ($str) = @_;
    return int(UnixDate($str, "%s")); 
}

sub secsDiff
{
    my ($str) = @_;
    return string2date($str) - string2date("now");
}

sub update_firetime
{
    my ($task, $now) = @_;
    my $new = $now;
    if(defined $task->{time})
    {
        $new = string2date($task->{time});
        $new += secsDiff("+ 1 day") if $new < $now;
    }
    elsif(defined $task->{step})
    {
        $new  = $now;
        $new += secsDiff($task->{step}) while $new <= $now;
    }
    $task->{fire_time} = $new;

}

sub boot
{
    my $now = string2date("now");    
    update_firetime($_, $now)
        foreach (@tasks);
}

sub execute
{
    my ($task) = @_;

    my $pid = fork();
    if((defined $pid) && ($pid == 0)) 
    {
        if(defined $task->{xterm} && $task->{xterm} == 1)
        {
            #boot and leave an xt
            my $label   = $task->{label};
            my $cmd     = $task->{cmd};
            my $sys_cmd = "xterm -xrm 'XTerm*foreground: red3' -xrm 'XTerm*background: black' -title 'CRONTAB:$label' -e sh -c \"$cmd; ksh\" &";
            
            system($sys_cmd);
        }
        else
        {
            #just execute it..
            system($task->{cmd});
        }
        exit(0);
    }
}

sub cron_core
{
    while(1)
    {
        my $now = string2date("now");
        foreach my $task (@tasks)
        {
            if($now > $task->{fire_time})
            {
                print "fire! $task->{label}\n";
                execute($task);
                update_firetime($task, $now) 
            }
        }
        #cron loop an launch
        
        print("sleeping.....\n");
        sleep($period);
    }
}

print "Operating with an accuracy of +/-$period seconds\n";

boot();
cron_core();

2 comments:

  1. Seems over elaborate way of running a polling script. while (1) { poll; sleep($interval); }
    Does not survive reboot unless you add it in to boot scripts, in which case you are better off arguing for crontab.

    ReplyDelete
  2. Yep dead on mate.. The servers im working with are the "loose 1 mil for every second its offline" systems(or so we are told..) So your points are valid but, the admins are nutty, paranoid and are experts at arse covering. In short ill never get any access to anything other then a basic shell period so its hack and slash time..

    Here is the uptime... shutdown once a every 2-3 months.. I can deal with that...
    > uptime
    04:56AM up 39 days, 16:27, 41 users, load average: 3.66, 3.76, 2.61

    ReplyDelete