Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: singleton lock not reliable

by NERDVANA (Friar)
on Jun 23, 2021 at 23:32 UTC ( #11134229=note: print w/replies, xml ) Need Help??


in reply to singleton lock not reliable

One entirely different solution is to move to some kind of process manager (who will guarantee that only one instance runs at a time) and then change your cron entry to tell the process manager to start the task. If the task is already running, the process manager will ignore the redundant request.

For example, if you use docker (which is a process manager in addition to a container manager) you could create a container that starts, performs the job of the script once, and exits. Then your cron command would be “docker start my-task-name”. Other process managers I like are perp, and runit.

Replies are listed 'Best First'.
Re^2: singleton lock not reliable
by cavac (Priest) on Jun 25, 2021 at 12:20 UTC

    crontab? File locks? docker???

    Writing a simple cyclic thingy isn't that hard. Let's say you have a program that calculates the meaning of life, the universe and everything. It takes a varying time to execute. You want to call it every ten seconds or so, except when it takes longer to run. First, we need the program:

    #!/usr/bin/env perl use strict; use warnings; sleep(int(rand(10) + 5)); print "42\n";

    Then we write a cyclic executive that keeps track of the run time of the external program (=the scheduler):

    #!/usr/bin/env perl use strict; use warnings; use Time::HiRes qw(time sleep); my $cmd = "./meaningoflifetheuniverseandeverything.pl"; my $cycletime = 10; while(1) { my $starttime = time; `$cmd`; my $endtime = time; my $timetaken = $endtime - $starttime; if($timetaken >= $cycletime) { print "Immediate restart\n"; next; } my $sleeptime = $cycletime - $timetaken; print "Sleeping for $sleeptime\n"; sleep($sleeptime); }

    This effectively implements a simple "minimum cycle time" scheduler:

    Sleeping for 0.986798048019409 Sleeping for 4.98646092414856 Sleeping for 3.98296499252319 Immediate restart Immediate restart Immediate restart Immediate restart

    If you want a more crontab like behaviour with start times aligned to specific times, you can use take the current time, calculate the modulos (division remainder) for the cycle time. Then calculate difference between that and a full cycle time interval how long to sleep. Like this:

    #!/usr/bin/env perl use strict; use warnings; use Time::HiRes qw(time sleep); my $cmd = "./meaningoflifetheuniverseandeverything.pl"; my $cycletime = 10; while(1) { my $endtime = time; my $sleeptime = $cycletime - ($endtime % $cycletime) - 1; if($sleeptime) { print "Sleeping for $sleeptime\n"; sleep($sleeptime); } `$cmd`; }

    Result:

    Sleeping for 9 Sleeping for 5 Sleeping for 9 Sleeping for 6 Sleeping for 6 Sleeping for 7

    This has a jitter of up to one second, but that should be acceptable enough, i think. Depending on your required time zone settings, you also might have to tweak the whole thing by about 37 seconds, plus/minus a couple of leap seconds every few years, something like this:

    my $TAIoffset = -37; ... my $endtime = time + $TAIoffset;

    But that's probably overkill for most purposes.

    perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
      > Writing a simple cyclic thingy isn't that hard.

      One of the advantages of cron is it's restarted when the machine is restarted or when it crashes for whatever reason. Instead of trying to achieve the same with a cyclic thingy, I'd rather go with crontab.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

        Good point. I was mostly trying to point out that using a complicated solution like Docker is a bit much for such a simple problem.

        perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11134229]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2022-08-14 09:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?