t-rex has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

In my script i give user a parameter where he mentions he wants to run this script for x number of hours, how should i implement this? I read online , one way could be using SIGALRM and writing handler for this so that when this is achieved I stop the script,

please suggest other efficient ways if there exist, thanks

P.S. : basically The script involves lot of forking, file transfers , socket connection, and we want to setup a cron job which runs everyday for 10 hours ( our script runs a tool which does regression), so I have an option to run the tool for some million passes or for lets say 10 hours. I hope I am clear now

thanks

Replies are listed 'Best First'.
Re: Perl script to run for x hours
by haukex (Archbishop) on Sep 27, 2016 at 10:49 UTC

    Hi t-rex,

    The best way to do that can vary depending on what the script is doing. Is it doing heavy calculations, reading from a file, network communication, ...?

    Also, see Alternatives to Mixing Alarm and Sleep.

    Regards,
    -- Hauke D

      hello,

      yes its doing heavy processing , sockets,file transfers, running some tools

        Hi t-rex,

        For things under your control (calculations, reading a file), you can implement the timeout yourself (e.g. marinersk gave a basic example). For network communication, you can usually specify timeouts after which the control will return to your script, at which point you can do your own timeout checks. For external processes, it really depends on the external process. You'll have to be a lot more specific in your question, otherwise the best we can do is general suggestions. I know what I mean. Why don't you? and How do I post a question effectively?

        Regards,
        -- Hauke D

Re: Perl script to run for x hours
by stevieb (Canon) on Sep 27, 2016 at 13:52 UTC

    For fun and learning last week, I wrote a timed event handler that can manage these things (there are FAR better ones on the CPAN, so look there if you want to go that route). There are many ways to do what you want, but as others have said, we need to know more info about what your script actually does. I just thought I'd throw this out there as an idea for one way.

    In this example, I've used a while() loop to simulate the workload, but that isn't necessary. I'll comment in code as to what is happening. $limit is the amount of time in seconds you want to run your script for (32400 for 9 hours). $interval is how often you want to check the runtime (in seconds again).

    use warnings; use strict; use Async::Event::Interval; # signal handler for when an interrupt signal is thrown $SIG{INT} = sub { cleanup(); }; my $limit = 10; my $interval = 3; my $parent_pid = $$; my @args = ($parent_pid, time(), $limit); # create the event in a separate process to 'monitor' the # runtime of the main (this) script my $event = Async::Event::Interval->new($interval, \&time_check, @args); $event->start; while (1){ # do stuff... sleep 1; } # this is our signal handler routine. It exits the main application. # the event automatically cleans itself up sub cleanup { print "time's up, exiting...\n"; exit; } # this is the event callback. It checks runtime, and when # reached, sends an interrupt signal to the parent process sub time_check { my ($parent_pid, $start_time, $limit) = @_; my $run_time = time - $start_time; if ($run_time >= $limit){ kill 'SIGINT', $parent_pid; } }
Re: Perl script to run for x hours
by Happy-the-monk (Canon) on Sep 27, 2016 at 13:31 UTC

    It so much depends on the precision of the job. Is it paramount to finish on time? Is the job to stop in-process when time is running out? Or is it rather unimportant?

    Imagine your boss is coming round telling you to manually stamp envelopes for the next two hours. No reprogramming any printers, hands off the keyboard. Take that stamp and stamp away.

    So you stamp an envelope each and then look at the clock or your watch, check the two hours haven't passed yet and proceed?

    Or you absentmindedly stamp away, always fixing the clock with your eyes and let the stamp fly out of your hands when time's finally out?

    In programming, you could calculate the time when to stop, create a sub stampit and a loop checking for the time out to be reached around calling that subroutine... in the first place. In the second, also check for the time inside the stamping routine and when time's out, leave it (i.e. return to end the loop) with the last; command.

    Cheers, Sören

    Créateur des bugs mobiles - let loose once, run everywhere.
    (hooked on the Perl Programming language)

Re: Perl script to run for x hours
by marinersk (Priest) on Sep 28, 2016 at 02:45 UTC

    As noted by others, what the script is doing generally drives the decision on how to implement the time limit.

    That said, if you have something that can run for hours, one hopes it is doing some menial task inside a loop. The most graceful (but to Happy-the-monk's point, not necessarily the most timely) approach, in my opinion, is to grab the time at the start of the loop, precompute the ending time, and then check current time at the top of the loop and see if we've passed the deadline.

    Something like this:

    #!/usr/bin/perl use strict; use warnings; my $run_limit_hours = 9; # You would of course grab this +from @ARGV or something my $start_time = time; # Number of seconds since epoch my $end_time = # Deadline -- end time in second +s-since-epoch $start_time + $run_limit_hours * 60 * 60; # 60 seconds per minute, 60 minu +tes per hour while (1) { my $current_time = time; if ($current_time > $end_time) { last; } &doTheThing(); } exit;