Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

How can i check my script is already running?

by shekarkcb (Beadle)
on May 11, 2010 at 09:39 UTC ( [id://839406]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,all

I need to put a check before running the script that if its already running then exit. I used below code but still failed to catch the issue. Can anybody help me ?

our ($CHECKRun,$localtime); $localtime=`date +%c`; chomp($localtime); $CHECKRun=`ps aux | grep -i "/home/shekar/myscript.pl" `; chomp($CHECKRun); print "I HAVE ps output|$CHECKRun|\n\n\n___________\n\n"; $CHECKRun=`ps aux | grep -ic "/home/shekar/myscript.pl" `; chomp($CHECKRun); if($CHECKRun gt 4) { print "got value of |$CHECKRun|, |CALLED ON |$localtime| looks + like Script already running...\n"; exit; }
Here myscript.pl is the script which has this code inside.
I used count as 4 because, whenever script is executed it gave me 4 as number so used 4 as counter.
This chunk of code is part of big script.Can anybody tell me where i am wrong?

Thanks,

Replies are listed 'Best First'.
Re: How can i check my script is already running?
by moritz (Cardinal) on May 11, 2010 at 09:46 UTC
    Can anybody tell me where i am wrong?

    First you tell us why you think something's wrong. In what way does it not do what you expect?

    Second, your approach is very fragile, there are several ways to call your script that will break it (for example by using relative paths, or symlinks to the script).

    Consider locking a particular file instead; you should find some examples here on perlmonks with Super Search.

    Perl 6 - links to (nearly) everything that is Perl 6.
      And in particular, locking the file of the program itself. For instance, by locking the *DATA file handle.
Re: How can i check my script is already running?
by Corion (Patriarch) on May 11, 2010 at 09:46 UTC
      I would create a pid file that tells you whether your program is running.
      There are two possible problems with that: it can generate false positives, and false negatives. If the pid file is removed for some reason, a next invocation can falsely determine no other invocation is running. OTOH, if an invocation dies unexpectedly, it may leave behind the pid file. By the time the program is invoked again, the pid may have been reused; the program would falsely determine there's another invocation, when there isn't. On top of that, to avoid race conditions, only one invocation should be able to modify the pid file at a time. But that means, in order to solve the problem (only one invocation at a time), you first have to solve the problem (only one invocation at a time accessing the pid file). You'd have to use file locks. But then you may as well use file locks in the first place.

      I'd only use a pid file if there's a benefit in knowing the pid of the running instance.

        If the pid file is removed for some reason, a next invocation can falsely determine no other invocation is running. OTOH, if an invocation dies unexpectedly, it may leave behind the pid file.
        If the pid contained in the pid lock file is not in the process table, you should display a message asking if the process is running. If not, you can prompt the user to remove the file.

        If the file does not exist (false negative), there is a logic error in your program (the pid lock file should be the first object created and the last destroyed).

        You'd have to use file locks. But then you may as well use file locks in the first place.
        The point of using a predictable lock file (program_name.pid) in a predictable location (/var/run ?) is to handle all of the situations you describe. Data files used by the program may or may not be predictable. Directory locations may or may not be predictable (relative vs. absolute paths).

        Using the conventions that have grown over the years (/var/run for pid lock files) work for a reason. YMMV

Re: How can i check my script is already running?
by shekarkcb (Beadle) on May 11, 2010 at 11:04 UTC
    Thank you all for the reply.
    I resolved the issue using this Node.
Re: How can i check my script is already running?
by hotpelmen (Scribe) on May 11, 2010 at 16:30 UTC
    Just a note: you need to exclude your "ps" check from the list of processes returned since it will also match your script path. Try this:
    my @np = `ps aux | grep "/home/shekar/myscript.pl" | grep -v grep`; print "Number of running processes: " . (scalar @np) . "\n";
    or
    my $np = `ps aux | grep "/home/shekar/myscript.pl" | grep -v grep | wc -l`; chomp $np; print "Number of running processes: $np\n";
    But I agree with others, you can find better ways to do it.
      Just a note: you need to exclude your "ps" check from the list of processes returned since it will also match your script path.

      I like to use the following trick, so as not to invoke an additional grep:

      $ ps aux | grep [i]nit root 1 0.0 0.0 23820 2024 ? Ss 08:23 0:01 /sbin +/init

      --
       David Serrano
       (Please treat my english text just like Perl code, i.e. feel free to notify me of any syntax, grammar, style and/or spelling errors. Thank you!).

Re: How can i check my script is already running?
by hossman (Prior) on May 12, 2010 at 01:21 UTC
Re: How can i check my script is already running?
by DrHyde (Prior) on May 12, 2010 at 09:59 UTC

    One obvious source of error is that 'ps aux' is not portable - it only works with GNU ps. It will not, for example, work on Solaris, or on Windows. Take a look at Proc::ProcessTable instead, which supports the most common Unix variants - still no Win32 support though.

    The approach taken by rsnapshot (backup software; needs to be safe and reliable) is to drop a PID file somewhere - the default is /var/run/rsnapshot.pid - and look for that when starting up. If it already exists, we read it to get the PID of the process that may be hanging around, and then try to send it a signal. If we can successfully send it a signal (ie, if a process with that PID exists) we log that, and stop. If there is no such process, then whether to continue or not is configurable.

    This is safe - it guarantees that (provided nothing else messes with the PID file!) you won't have two instances of rsnapshot running at once. And it's *failsafe* because if rsnapshot exits without cleaning up the PID file *and* that PID is in use by something else next time rsnapshot runs, it still won't run. Better to miss a backup than to potentially have two backups fighting each other and screwing up.

      I would not consider a backup program "safe", "failsafe" or "reliable" if it stops working just because it left some arbitary file after a crash and refuses to write backups after that until someone manually removes that file. And I wouldn't consider it "safe", "failsafe" or "reliable" if it stops working because some long-running daemon accidentally has the process ID stored in that file.

      PID files always cause race conditions, that's why I don't use them.

      For daemons, the daemontools work fine without PID files, and as a nice side effect of the management done by daemontools, there is at any time at most one instance of any daemon under control of daemontools.

      For other programs, one has to define for which "circle" the "only one instance at a time" rule applies. Only one instance per machine works fine with a lock on the executable itself. Only one instance per machine per user already becomes difficult, because locking the executable would lock out other users. So one has to use a dedicated lock file below the users home directory. Only one instance per local network can become really tricky. With a distributed lock manager, you could still get away by locking a file on a shared drive, else you would need to implement some kind of IPC. And as soon as the circle becomes larger than a network of connected machines, I don't see any technical solution to prevent multiple instances.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-04-24 04:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found