stellagoddc has asked for the wisdom of the Perl Monks concerning the following question:

Monks,

I'm trying to create a script that will do particular sub routines at specific intervals. i.e. Every 10 seconds run sub1() , 25 seconds run sub2() and every 60 seconds run sub3().

I've done some searches for code or modules but can't seem to find anything that can get me started, any pointers?

Upadte **********************

Thanks, let me add a little more detail.

I currently have a script which fires of a load of threads, to do SNMP polls on particular devices, each poll getting its own thread. I dont want to have a thread per device constantly running, especially if all its doing is sleeping.

So I suppose what I'm after is the ability to fire the same routine of (as a thread) every 20 seconds for device A, every 30 seconds for device B etc.

I was planning on reading in the device -> polling rate realtionship from a file. So it has to be a little dynamic.

Thanks

The True StellaGod

2006-04-20 Retitled by GrandFather, as per Monastery guidelines
Original title: 'Timed Subroutines'

Replies are listed 'Best First'.
Re: Running subroutines at specific times
by blazar (Canon) on Apr 20, 2006 at 16:15 UTC

    Seems like an event driven thing... but do you want the code in the various subs to run asynchronously? Can it possibly last more than the given amount of time? if so then you {c,sh}ould fork or use threads. Else you may be interested in alarm.

    All in all seems more like stuff for cron. In perl, you may just have an infinite loop with a sleep 1 holding a counter. If, say, $counter % $interval == 0 then this will trigger the wanted action. Of course you can and probably want to have @interval or %interval instead of $interval.

      Thanks, let me add a little more detail.

      I currently have a script which fires of a load of threads, to do SNMP polls on particular devices, each poll getting its own thread. I dont want to have a thread per device constantly running, especially if all its doing is sleeping.

      So I suppose what I'm after is the ability to fire the same routine of (as a thread) every 20 seconds for device A, every 30 seconds for device B etc.

      I was planning on reading in the device -> polling rate realtionship from a file. So it has to be a little dynamic.

      Thanks again.

      Blazar,

      I think that might just do it.

      Thanks a lot

Re: Running subroutines at specific times
by saintmike (Vicar) on Apr 20, 2006 at 16:46 UTC
    POE provides a framework for this kind of thing and much much more:
      2006/04/20 10:57:59 sub10
      2006/04/20 10:57:59 sub15
      2006/04/20 10:58:09 sub10
      2006/04/20 10:58:14 sub15
      2006/04/20 10:58:19 sub10
      2006/04/20 10:58:29 sub10
      2006/04/20 10:58:29 sub15
    
    use POE; use Log::Log4perl qw(:easy); Log::Log4perl->easy_init($DEBUG); POE::Session->create( inline_states => { _start => sub { $poe_kernel->yield("sub10"); $poe_kernel->yield("sub15"); }, sub10 => \&sub10, sub15 => \&sub15, }); $poe_kernel->run(); sub sub10 { DEBUG "sub10"; $poe_kernel->delay("sub10", 10); } sub sub15 { DEBUG "sub15"; $poe_kernel->delay("sub15", 15); }
Re: Running subroutines at specific times
by jdhedden (Deacon) on Apr 20, 2006 at 16:15 UTC
    You can either try the Event module, or use a threaded app where the subs loop continuously with sleeps of the appropriate duration.

    Remember: There's always one more bug.
      Thanks, let me add a little more detail.

      I currently have a script which fires of a load of threads, to do SNMP polls on particular devices, each poll getting its own thread. I dont want to have a thread per device constantly running, especially if all its doing is sleeping.

      So I suppose what I'm after is the ability to fire the same routine of (as a thread) every 20 seconds for device A, every 30 seconds for device B etc.

      I was planning on reading in the device -> polling rate realtionship from a file. So it has to be a little dynamic.

        Thanks, let me add a little more detail.

        Whatever the details may be, you already explained them in this post of which this one is a dupe, which is the reason why I and apparently others downvoted it. Regardless of the details, it seems to me that people supplied enough input already, are you having problems with any of these suggestions? I see that saintmike supplied a complete example, and BrowserUk suggested another approach, which should be more near to your original attempts. If you're having any specific problem with those suggestions, feel free to ask for further clarification...

Re: Running subroutines at specific times
by salva (Canon) on Apr 20, 2006 at 16:23 UTC
    You can use an event based framework like Event to do that. The repeat.t script on the demo directory from this module shows you how to set timers.

    As your requirements are quite simple, you can also write a simple scheduler yourself around the sleep function.

Re: Running subroutines at specific times
by BrowserUk (Patriarch) on Apr 20, 2006 at 23:21 UTC
    I dont want to have a thread per device constantly running, especially if all its doing is sleeping.

    Why not?

    This would be how I would do it. Note, I've no way to test the SNMP stuff, so I've just cleaned up the code you posted elsewhere.

    #! perl use strict; use threads; use threads::shared; use Net::SNMP; sub polldevice { my( $running, $stop, $host, $community, $delay ) = @_; ++$running; my( $session, $error ) = Net::SNMP->session( Hostname => $host, Community => $community ) or die "session error:" . $session->error; do { my $result = $session->get_request( "1.3.6.1.2.1.1.2.0", "1.3.6.1.2.1.2.1.0", "1.3.6.1.2.1.1.3 +.0" ) or die "request error: " . $session->error; print "Testing ".$host."\n"; print "Number of interfaces: ".$result->{"1.3.6.1.2.1.2.1.0"}. +"\n"; print "uptime: " . $result->{"1.3.6.1.2.1.1.3.0"}."\n"; print "sysOID: " . $result->{"1.3.6.1.2.1.1.2.0"}."\n"; } while not $stop and sleep $delay; $session->close; --$running; } my $stop :shared = 0; my $running :shared = 0; while( <DATA> ) { async{ \&polldevice, $stop, split ' ' }->detach; } $SIG{INT} = sub{ $stop = 1 }; sleep 1 until $stop; sleep 1 while $running; __DATA__ 192.168.1.50 public 10 192.168.1.1 public 25 192.168.1.2 public 60 192.168.1.3 public 45 192.168.1.4 public 12 192.168.1.5 public 59 192.168.1.6 public 01

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Running subroutines at specific times
by TedPride (Priest) on Apr 20, 2006 at 17:06 UTC
    Just store this as a queue of arrays, each array containing a sub ref, next timestamp to run the sub, and interval. Then sleep for however many seconds until the next item in the queue is up for running, add interval seconds to the timestamp, requeue, and run the sub. Rinse and repeat. All you need is a priority queue (or heap) module and about 5 minutes of elementary programming.

    Of course, if this is an ongoing thing and needs to run 24/7, you may wish to do what blazar suggests and use cron, which was designed specifically for doing this sort of thing.