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

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

Hola Monks,

Last week, I asked how to ensure that my Perl script wouldn't run if another instance of the same script was running. (Post was: "Mechanism for ensuring only one instance of a Perl script can only run?", Dec 2 2022) The solution that you guys suggested recommended taking advantage of flock() as a mechanism. (Thank you!!!) The basic implementation idea was simple: It my script ran and did not see an empty "lock file" in the local directory, it would create one and then flock() that file to lock it. Upon exiting, it would delete the file. If another instance of the same script ran and saw the lock file, it would immediately terminate. This was the "There Can Be Only One" (Highlander) approach.

I implemented this idea, but ran into management issues with the lock file. (The lock file was not deleted properly, it was overwritten, etc.) So I went back to the drawing board.

What do you think of this approach:

#!/usr/bin/perl use warnings; use strict; package main; my $name = `basename "$0"`; # Get this script's name $name =~ s/\R//g; # Chop off trailing newlines print "Script name is: \"$name\".\n"; my $dirPerl = "/usr/bin/perl"; my $psCmd = "ps -ef | grep $name"; my $scriptRunningCount = 0; my $output = qx($psCmd); # Run "ps -ef | grep SCRIPTNAME" foreach my $line (split /[\r\n]+/, $output) { if( index($line,$dirPerl) != -1 && index($line,$name) != -1 +){ $scriptRunningCount++; } } if($scriptRunningCount == 1){ # ...run script... } print "END OF PROGRAM.\n";

This code literally does what I would do; it issues a `ps -ef` and makes sure it is the only script of its instance running. No flock() command, no managing an external file.

I'm still a Perl newbie. To me, the above is simpler... perhaps too simple. You guys are the experts, so I'm (humbly) asking for a Pros-Vs-Cons critique of this idea. If I only want one instance of my script to run, is the above code a solid approach? All criticisms are welcome. Thank you!

  • Comment on Ensure Only One Instance of Your Script is Running... with 'ps -ef' ?
  • Download Code

Replies are listed 'Best First'.
Re: Ensure Only One Instance of Your Script is Running... with 'ps -ef' ?
by hippo (Archbishop) on Dec 05, 2022 at 23:33 UTC
    I implemented this idea, but ran into management issues with the lock file. (The lock file was not deleted properly, it was overwritten, etc.)

    Neither of these situations is a problem. The lockfile is only there to be locked. If it is absent, then there is no lock. If it is present a lock should be attempted. The contents of the file (if any) are irrelevant.

    You have presented an alternative which is, by comparison, brittle. It relies on shelling out a lot and we know from experience that this can lead to problems.

    If managing your own lockfiles with flock is too tricky then why not simply use Script::Singleton as stevieb suggested here? That's a simple, reliable solution.


    🦛

      Thanks hippo, Appreciate you ruling that my second solution is "brittle"; that's the kind of expertise I lack and why I like this site so much. Appreciate the advice! I'm looking into Script::Singleton, as that sol'n looks perfect...
Re: Ensure Only One Instance of Your Script is Running... with 'ps -ef' ?
by bliako (Abbot) on Dec 05, 2022 at 23:25 UTC

    why re-invent the wheel when there is already Proc::ProcessTable which you can enquire about your current processes? (and this approach was already mentioned in your previous question, see Re: Mechanism for ensuring only one instance of a Perl script can only run?)

    Secondly, you hardcode /usr/bin/perl in the shebang and also in the script but those who will inherit the script will know that? And you assume that who runs the script will do it without appending it with a perl interpreter executable.

    Thirdly, "simpler" may be but does it work under all conditions and circumstances? Hmmm. I would say, stick either with flock/highlander or with the shared-memory approach of Script::Singleton (my preference is with the memory-based approach which is more universal than the file-system approach).

    Btw, if( index($line,$dirPerl) != -1  &&  index($line,$name) != -1 ) can be replaced with a regex

      Thanks bliako, Appreciate all that you say. I couldn't get the Proc::ProcessTable approach to work, sadly. My flock/highlander attempt ran into problems, too, which is why I'm back with more desperate ideas. I like the look of Script::Singleton, perhaps I'll try that next.
Re: Ensure Only One Instance of Your Script is Running... with 'ps -ef' ?
by LanX (Saint) on Dec 05, 2022 at 22:21 UTC
    I think you are applying flock in a wrong way, which offers race conditions.

    The lock must happen in one atomic step and only the script having the lock must be allowed to write. Not the script which created the locked file.

    Did you try the code I offered?

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery

    Edit

    Improved wording

Re: Ensure Only One Instance of Your Script is Running... with 'ps -ef' ?
by stevieb (Canon) on Dec 06, 2022 at 06:34 UTC

    Shout out to bliako for this:

    Hmmm. I would say, stick either with flock/highlander or with the shared-memory approach of Script::Singleton (my preference is with the memory-based approach which is more universal than the file-system approach).

    ...and hippo for this:

    If managing your own lockfiles with flock is too tricky then why not simply use Script::Singleton as stevieb suggested here? That's a simple, reliable solution.
    .

    When I read things like this it becomes apparent that my dedication to Perl (and Open Source in general) is acknowledged and appreciated. Thank you guys! It's all of you that keeps me going.

    With that said, to anyone new or just coming up, work hard. Ask questions. Answer questions. Put something on the CPAN. I am paid because I put stuff on the CPAN. Perl is a very high paying profession. Become trusted in the Perl ecosystem and you will have a career.

    I have, myself had influence on several hires. If you have a CPAN profile, you've contributed. It doesn't matter if you're embarrassed. Just get work in the open. The willingness to get something in public is more important than how 'good' the work is. Being public is far more important than having publicity.

    Your resume/CV is "where's your Github/CPAN". Just get your code out there, no matter how bad or good you think it is. I've helped hire people because they've published something over those who haven't. Code I perceive as horrible that is published globally is far better than awesome code that isn't. I want someone who is confident in what they do; not someone who's waiting until they write the best thing. Technique can be trained; confidence can not.

    My theory is if there's as close to 100% test coverage, it doesn't matter how good the code does; it's assured the code does what it says it does.

    Tests. Documentation. Code. Publish. Be acknowledged.

    Merry Christmas!