Search code examples
linuxbashpidflocklockfile

What is the best way to ensure only one instance of a Bash script is running?


What is the simplest/best way to ensure only one instance of a given script is running - assuming it's Bash on Linux?

At the moment I'm doing:

ps -C script.name.sh > /dev/null 2>&1 || ./script.name.sh

but it has several issues:

  1. it puts the check outside of script
  2. it doesn't let me run the same script from separate accounts - which I would like sometimes.
  3. -C checks only first 14 characters of process name

Of course, I can write my own pidfile handling, but I sense that there should be a simple way to do it.


Solution

  • If the script is the same across all users, you can use a lockfile approach. If you acquire the lock, proceed else show a message and exit.

    As an example:

    [Terminal #1] $ lockfile -r 0 /tmp/the.lock
    [Terminal #1] $ 
    
    [Terminal #2] $ lockfile -r 0 /tmp/the.lock
    [Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"
    
    [Terminal #1] $ rm -f /tmp/the.lock
    [Terminal #1] $ 
    
    [Terminal #2] $ lockfile -r 0 /tmp/the.lock
    [Terminal #2] $ 
    

    After /tmp/the.lock has been acquired your script will be the only one with access to execution. When you are done, just remove the lock. In script form this might look like:

    #!/bin/bash
    
    lockfile -r 0 /tmp/the.lock || exit 1
    
    # Do stuff here
    
    rm -f /tmp/the.lock