http://www.perlmonks.org?node_id=1219754

dideod.yang has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks I have question. I wonder How to do some command every X seconds during working other command. below example, I want to check File list every 5 seconds during working some jobs in scripts. Do you have any idea? Please help monks.. :)
# doing every 5 seconds print "Checking FILE...Every 5 seconds\n"; `ls file | grep test`; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs"; print "Doing Jobs";
#I want to print that Doing Jobs Doing Jobs Doing Jobs Checking FILE...Every 5 seconds Doing Jobs Doing Jobs Doing Jobs Doing Jobs Checking FILE...Every 5 seconds Doing Jobs ...

Replies are listed 'Best First'.
Re: Doing every X seconds
by tbusch (Sexton) on Aug 04, 2018 at 21:54 UTC
    #!/usr/bin/perl use strict; $SIG{ALRM} = sub { print "do something else\n"; alarm 3; }; alarm 3; while (1) { sleep 1; print "do some work\n"; }
      ++!
Re: Doing every X seconds
by Marshall (Canon) on Aug 03, 2018 at 06:00 UTC
    I would like to know more about your application before proposing a solution.
    What code do you have now?
    How does this surveillance of a file for the keyword "test" factor into that?
    Is this file being modified by other means than a simple append by another process?
    How are you keeping track of what has done before?
    Does "doing jobs" have to happen in parallel? If so, why so?
Re: Doing every X seconds
by Theodore (Friar) on Aug 03, 2018 at 10:19 UTC
Re: Doing every X seconds
by kcott (Archbishop) on Aug 05, 2018 at 20:52 UTC

    G'day dideod.yang,

    As you can see, a lot of possibilities have been suggested: threads, fork, alarm, IO::*, and just to throw another into the mix, Tk::after might be what you want in a Tk GUI.

    As already requested by ++Marshall, please provide a more concrete context than "some jobs in scripts". Thanks.

    — Ken

Re: Doing every X seconds
by vinoth.ree (Monsignor) on Aug 03, 2018 at 04:38 UTC

    I hope you need threads

    Create two threads,
    1.First thread for normal flow (print("Doing Jobs";))
    2.Second thread for (Checking FILE...Every 5 seconds)
    

    All is well. I learn by answering your questions...
Re: Doing every X seconds
by anonymized user 468275 (Curate) on Aug 03, 2018 at 07:52 UTC
    This looks more like a perlfork requirement to me, although we need to check child alive without wait. Example:
    use POSIX ":sys_wait_h"; my $child = fork; if ($child) { # parent case my $res; while (not ($res = waitpid($child, WNOHANG))) { sleep 5; # check file list here # ... } if ($res == -1) { warn "fatal child error\n"; exit; } } else { # child case # insert job processing here exit; # child must explicitly exit otherwise both would continue e +xecuting this } # reach here if job processing completed successfully
    (code updated)

    One world, one people

      You forgot to check the definedness of $child, as upon failure to fork you'll get undef. You likely do not want to pretend you're supposed to be executing the child case code in that circumstance.

      I'm puzzled by "# child must explicitly exit otherwise both would continue executing this". The wording suggests both parent and child will continue executing the child case which of course is untrue. As written, the child would fall out of the else clause and the parent's waitpid would still see the child's exit status if that call to exit were not present. You then say to "# reach here if job processing completed successfully" which in your case only the parent will and the child won't because of the above-mentioned exit. Perhaps it would be clearer for the first one to say "... or the child will continue past the else block and we only want the parent to do so" or something similar.

      If the intent is for both programs to be done after the branch, a shared exit just after the entire if statement could be useful. Any code you intend for the parent only to run after the child is gone could be placed in the parent's case in the if block, after the loop on waitpid. It's also possible to have the parent exit and the child continue, and that's desirable under certain circumstances.

      At this point I think it's worth mentioning there are tools to do this handling for you. Depending on your exact needs, there are Parallel::ForkManager, AnyEvent::ForkManager, IPC::Run, IPC::Run3, Proc::Fork, Proc::Fork::Control, Proc::Daemon, and a whole lot more.

      A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Doing every X seconds
by ikegami (Patriarch) on Aug 07, 2018 at 12:15 UTC
    use Time::HiRes qw( sleep ); my $interval = 3; my $min_sleep = 0; my $sleep_until = time; while (1) { work(); $sleep_until += $interval; my $now = time; my $sleep_for = $sleep_until - $now; if ($sleep_for < $min_sleep) { warn("Work took too long\n"); $sleep_for = $min_sleep; $sleep_until = $now + $sleep_for; } sleep($sleep_for) if $sleep_for; }
Re: Doing every X seconds
by karlgoethebier (Abbot) on Sep 07, 2018 at 10:25 UTC

    You may take a look at Parallel trigger of different subs and try to modify some of the examples for your needs.

    Minor Update: Slightly better wording.

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help