http://qs1969.pair.com?node_id=11148499

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

Hola Perl Monks,

So I have a Perl (v5.30.0) script that is run every five minutes via a crontab on my Ubuntu server. When I first wrote the script, I thought five minutes would be plenty of runtime. But recently, I've discovered that the script may require *more* than five minutes to complete execution. This is a problem.

Right now, say my script is executed at 12:00. It does reads and writes to disk and to the network. But when the clock strikes 12:05, the script is not finished. It keeps going. But then cron runs a second instance of the script. Now the 12:00 and 12:05 scripts are both reading and writing the same data to disc & network. They complicate each other's work, data is contaminated, and the mess is still getting worse when the 12:10 instance of the script arrives on the scene. Mass hysteria follows.

So now I need a mechanism where my script basically makes sure there are no other instances of itself running. Pseudocode would be:

Script starts. Am I the only instance of this code? -- If YES, continue -- If NO, terminate immediately

This can't be that hard to do. That said, whenever I think about it, I come up with fairly clunky solutions. Below is code which technically works... but is a pretty stupid solution. Basically, the script creates an empty file (I'm calling it a "Marker File") at the start of execution, then deletes it at the end. If another instance of the script starts and sees that file, it realizes that its not alone and terminates.

This will work... but I kinda superhate it. It takes 20 lines of code to do something that seems pretty basic. Can you recommend a more elegant solution? There's gotta be a way. Thank you.

My code:

#!/usr/bin/perl use warnings; use strict; my $MARKER_FILE="/home/me/MARKERFILE"; sub checkMarker { if(-e $MARKER_FILE){ # Marker file already exists, another instance of this + script is running! return undef; # FALSE } else { # Marker file doesn't exist! We should create one... my $cmd = "touch $MARKER_FILE"; `$cmd`; return 1; # TRUE } } package main; if (checkMarker()) { print "I can do stuff!\n"; # ...do stuff... my $endCmd = "rm $MARKER_FILE"; `$endCmd`; } else{ print "Another instance of this script is running, I can't run +...\n"; }