2

Possible Duplicate:
Quick-and-dirty way to ensure only one instance of a shell script is running at a time

I am new to shell script.

what I wanna do is to avoid running multiple instances of a script.

I have this shell script cntps.sh

#!/bin/bash
cnt=`ps -e|grep "cntps"|grep -v "grep"`
echo $cnt >> ~/cntps.log
if [ $cnt < 1 ];
then 
    #do something.
else
    exit 0
fi

if I run it this way $./cntps.sh, it echoes 2

if I run it this way $. ./cntps.sh, it echoes 0

if I run it with crontab, it echoes 3

Could somebody explain to me why is this happening? And what is the proper way to avoid running multiple instances of a script?

Community
  • 1
  • 1
SparedWhisle
  • 1,370
  • 2
  • 10
  • 20

3 Answers3

2

I changed your command slightly to output ps to a log file so we can see what is going on.

cnt=`ps -ef| tee log | grep "cntps"|grep -v "grep" | wc -l`

This is what I saw:

32427 -bash
  20430 /bin/bash ./cntps.sh
    20431 /bin/bash ./cntps.sh
      20432 ps -ef
      20433 tee log
      20434 grep cntps
      20435 grep -v grep
      20436 wc -l

As you can see, my terminal's shell (32427) spawns a new shell (20430) to run the script. The script then spawns another child shell (20431) for command substitution (`ps -ef | ...`).

So, the count of two is due to:

  20430 /bin/bash ./cntps.sh
    20431 /bin/bash ./cntps.sh

In any case, this is not a good way to ensure that only one process is running. See this SO question instead.

Community
  • 1
  • 1
dogbane
  • 266,786
  • 75
  • 396
  • 414
1

Firstly, I would recommend using pgrep rather than this method. Secondly I presume you're missing a wc -l to count the number of instances from the script

In answer to your counting problems:

if I run it this way $./cntps.sh, it echoes 2

This is because the backtick call: ps -e ... is triggering a subshell which is also called cntps.sh and this triggers two items

if I run it this way $. ./cntps.sh, it echoes 0

This is caused as you're not running, it but are actually sourcing it into the currently running shell. This causes there to be no copies of the script running by the name cntps

if I run it with crontab, it echoes 3

Two from the invocation, one from the crontab invocation itself which spawns sh -c 'path/to/cntps.sh'

Please see this question for how to do a single instance shell script.

Community
  • 1
  • 1
Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
0

Use a "lock" file as a mutex.

if(exists("lock") == false)
{
    touch lock file // create a file named "lock" in the current dir
    execute_script_body // execute script commands
    remove lock file // delete the file
}
else
{
    echo "another instance is running!"
}

exit
Gianluca Ghettini
  • 11,129
  • 19
  • 93
  • 159