Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am wondering if there is some tool/app which could prevent another tool/app from running more than once. I know it can be done manually by using pidfile but isn't there some tool for that?

Like: /bin/ruonce /bin/myApp

It would return 0 when the app is spawned for the first time in the background, 1 when it is already running..

In OpenRC there is start-stop-daemon which is close, but it's unnecessarily complex and not standalone.

share|improve this question
    
Yep, good question. You are really asking about the capabilities of the various service frameworks that exist in Linux space, like Upstart or systemd. Don't have the answer for you except frustration of the level this is at in Linux world. (I'm trying to transition from more enterprise like Unices, like Solaris and AIX and have posted this question.) –  unixhacker2010 Dec 1 '13 at 12:57
    
@unixhacker2010 Take a look at Monit as a way to add protection around system services/daemons. It's used quite heavily. –  ewwhite Dec 1 '13 at 13:00
    
Does Monit solve the run-only-once requirement? –  unixhacker2010 Dec 1 '13 at 13:07

3 Answers 3

up vote 7 down vote accepted

There's a simple utility called flock that will wrap a process in a lockfile and by default creates an exclusive lock. This means that subsequent runs of the process wrapped by the flock file will fail if the previous invocation is still running.

You can also tell flock to fail immediately instead of wait for the lock:

flock -xn /bin/yourcmd

This binary is a part of the util-linux package which should be available by default on your distro of choice.

share|improve this answer
    
Yep, that looks good, thanks. I was able to test it like this: flock -n /tmp/lock -c "/bin/sleep 10" –  kexik Dec 1 '13 at 20:51

Nothing else comes to mind.

However, what you are wanting is a script you could easily write. The requirements would be (not in programmatic order):

  • Start the process and store the PID in some way that uniquely identifies the program being run
  • Check that if there is a PID file, the PID in it corresponds to an existing instance of that program; if it does, abort; if it doesn't, start the process as normal and replace the PID file
  • Return your status

This is much of the functionality of start-stop-daemon, so it does lead one to wonder why you don't simply ignore the functionality in that which you don't need, and use it. You could even make a script or an alias to wrap it so that you could type a very small amount of characters.

For the sake of interest, you can also do this without PID files and catch all processes running with a particular filename (not pathname) whether started "properly" or not, by using pidof in your script.

share|improve this answer
    
Thanks for the response. I asked more for the same of interest if there is some app like runonce so I don't have to write it myself in bash script... –  kexik Dec 1 '13 at 12:50

You can do this with a lockfile routine (usually a directory) in your script... PID is the right way to handle this, but the lock file could be a quick way of achieving what you want. Also see this StackOverflow solution.

An example with explanation from a Perl script I use often. It can only have one instance running at a time:

# Set two variables that are used by the code that ensures that only
# one Orca process is using a particular configuration file at a
# particular time.  This is done by using the fact that mkdir() is
# atomic.  The first variable is the name of the directory to create
# and the second is a flag used by the Orca clean up code to see if
# the locking directory should be removed.
my $locking_directory       = "$config_filename.lock";
my $rmdir_locking_directory = '';

# Install signal handlers to clean Orca up, including the locking
# directory.
$SIG{INT}     = \&catch_signal;
$SIG{PIPE}    = \&catch_signal;
$SIG{TERM}    = \&catch_signal;
$SIG{__DIE__} = \&catch_die;

# Now try to create the locking directory.
unless (mkdir($locking_directory, 0755)) {
  die "$0: cannot create locking directory '$locking_directory': $!\n";
}
$rmdir_locking_directory = 1;
share|improve this answer
1  
Good one. The thing is that to do this right it is not enough to have a PID file you also need a mechanism to guard against race conditions... which is what you do above. But from a broader perspective I do think this is something that should be a handled by some kind of Linux service framework that we could all benefit from ... instead of having to write our own error prone scripts. Upvote for pointing out that a lock mechanism is required. –  unixhacker2010 Dec 1 '13 at 13:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.