This can be achieved with pid files. Example: http://candrews.integralblue.com/2009/02/one-instance-at-a-time-with-pid-file-in-bash/

Another clever way is to look thru the processes list (if your allowed to look thru all user – if not then either way this might still work for you if you dont think other users will be launching the program your writing)

Put this interesting “if” block at the beginning of your scripts

#!/bin/bash
# filename: SCRIPT1.sh

# if running dont start
# list all pids running with our program name, take out our pid, if one still in list, then others running (exit status 0). exit if others running.
if ps ax | egrep -v "grep|watch" | grep "SCRIPT1" | awk '{print $1}' | grep -v $$ | grep -q .; then
    echo "$0 STILL RUNNING - CLOSING";
    exit 1
fi

### rest of the script ###

“ps ax” will list all of the processes (pids in first column) then we grep out “greps” and “watch” (just in case SCRIPT1 was ran in a watch). Then we look for all of SCRIPT1 instances in the process list with that first grep. We then isolate the first column with an awk (optional, but hey maybe our SCRIPT line randomly has the processes id somewhere else). And finally we remove our own process id from the list (with grep $$, $$ is a bash trick to return our own PID). Now with the list of all of the running SCRIPT1s, if we remove our current process id (which is running our current instance of SCRIPT1), then we will be left with the list of the remaining running SCRIPT1s & their process ids. If that list is empty (nothing was returned), there are no other SCRIPT1s running, then exit status is 1, the if block is skipped and the “### rest of the script ###” is run. However If that list has something then there is another SCRIPT1 running. “grep .” at the end just matches for anything (That is not whitespace). If its output is empty, its exit status is 1(the script continue to run the rest of its code), if it has something its exit status is 0. Exit status 0 (meaning another SCRIPT1 is running) then we process the if block code.

Note: I use -q (quiet) on the last grep so we dont see its output as we just need to get its exit status for the if

So a more compact way could be this:

#!/bin/bash
# filename: SCRIPT1.sh

# if running dont start
# list all pids running with our program name, take out our pid, if one still in list, then others running (exit status 0). exit if others running.
if ps ax | egrep -v "grep|watch" | grep `basename $0` | grep -v $$ | grep -q .; then
    echo "$0 STILL RUNNING - CLOSING";
    exit 1
fi
### rest of the script ###

NOTE: $0 lists our program name. basename $0 lists just the filename (no path). $$ lists our process id.

NOTE: Also understand that if SCRIPT1 forks or whatever app we put in place of SCRIPT1 then this might not work. Because forks create more lines in grep, and I havent thought how this would play out (it might play out as intended and well)

NOTE: Running echo $$ in the shell gives the PID of the bash shell.

…The end…

Leave a Reply

Your email address will not be published. Required fields are marked *