Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re: Preventing multiple instances

by hippo (Bishop)
on Dec 16, 2020 at 22:00 UTC ( [id://11125306]=note: print w/replies, xml ) Need Help??


in reply to Preventing multiple instances

How can I prevent more than one instance of a script from running?

Lockfiles!

I have at times used a lockfile but there is always the risk that the power could go off or some other catastrophe could occur between the lockfile being created and being removed. So is there a better way to do it?

It's not necessarily the presence/absence of the lockfile that matters but rather the lock on that file. Locks don't persist through reboots so that problem is solved. See eg. the FAQ How can I lock a file?

Another file-based approach is a PIDfile. You store the PID of the running process in the file and on subsequent runs check that that PID does not exist (or doesn't relate to the process you are running). Still use locks on the PIDfile during access to avoid race conditions, of course.


🦛

Replies are listed 'Best First'.
Re^2: Preventing multiple instances
by jcb (Parson) on Dec 17, 2020 at 05:18 UTC

    PID files have a "fun" gotcha in daemons started as part of system boot — two instances of the same daemon may well get the same PID!

    This does not prevent using a PID file, after all, you know that this instance of the program has not written the PID file yet, so if you read it and find that it matches $$, you know the PID has been recycled across reboots.

    Perhaps the best option would be to place the PID file on a RAM filesystem that starts out empty every time the system boots. This way, there is no possibility of a stale PID file from the previous session and you avoid needless flash writes as a bonus.

    Even if the daemon is run from cron, this issue could bite our questioner — the daemon reboots the system if the time is not set within some grace period, so a network failure could cause the system to start, fail to set the clock, reboot, start the daemon with the same PID again, fail to set the clock, ...

      Assuming that the process is not running as root, you can kill -0 $(cat /path/to/file.pid) to see if the current user owns that process, or if it's running at all. Of course, lock the file before checking, and write the correct pid with the same lock.

      There is Proc::Daemon which can take a pid file, but I haven't used it, so I don't know if it does the right thing.

      Even if the daemon is run from cron, this issue could bite our questioner

      The unit is going to be installed in an environment whereby it cannot do anything to alert anyone to its distress if there is an ongoing problem. If it cannot get the time, it cannot function. The only way I will know is by checking if it is reporting in to the server regularly which it is configured to do each time it opens or closes the curtains.

      For that reason, I have re-written the above code so that a lockfile is not necessary. Instead, if the time is not set correctly, it logs the problem, increments a counter in the config file and exits. Next time it gets fired up by cron it has another chance to check the time but will reboot if it has been restarted 15 times as half an hour should be plenty of time for the router to come back to life after a power failure is restored.

      my @time = localtime; $control->log("Starting Curtain Controller") if $DEBUG > 1; # Check Pi has valid time if ($time[5] + 1900 < 2020) { my $restart = $local_conf->key('RESTART COUNT'); if ($restart > 15) { $control->log("Still no valid time - rebooting!"); $local_conf->key('RESTART_COUNT', '0'); sleep 2; system("reboot"); exit 0; } $control->log("No valid time is set - exit $restart"); $restart++; $local_conf->key('RESTART_COUNT', $restart); exit 0; } $local_conf->key('RESTART_COUNT', '0');

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2024-04-25 12:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found