I need to ensure that only one copy of my Perl script is running at a time. According to the suggestions here I wrote a sub to do the check:
sub check_instances {
open my $fh, '<', $0 or die $!;
unless (flock($fh, LOCK_EX|LOCK_NB)) {
print "$0 is already running. Exiting.\n";
exit 1;
}
}
But it doesn't work. What can be the issue?
You're using a lexical filehandle scoped inside the sub. When check_instances
returns, the filehandle is automatically closed, which releases the lock. So you'll never see a conflict unless two copies check at exactly the same time.
Ensure that the filehandle remains open as long as the script is running (or as long as you want to maintain the lock). For example:
{
my $fh;
sub check_instances {
return if $fh; # We already checked
open $fh, '<', $0 or die $!;
unless (flock($fh, LOCK_EX|LOCK_NB)) {
print "$0 is already running. Exiting.\n";
exit 1;
}
}
} # end scope of $fh
This would also be a good place to use a state
variable, if you can require Perl 5.10.
You can check the process list for other instances (Proc::ProcessTable can help), but a common route taken by unix programs in many languages is to create a pid file -- see File::Pid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With