How to check if a shell is already running ?

Hi,
I put this at start of my shell (korn shell) to be sure that the shell is not already running and sometimes it fails and says that it is already running which is not true !

sleep 1
/usr/bin/ps -ef | /usr/bin/grep "$0" | /usr/bin/egrep -v grep>$LOGDIR/$0.res
isup=$(cat $LOGDIR/$0.res|wc -l)
if [[ $isup -gt 1 ]]
then
print "$0 is already running - Aborting"
rm $LOGDIR/$0.res
exit 0
fi

Does someone knows a better way to do this ?

What exactly are you trying to achieve here? Ensure that you are not in a nested shell, i.e. that SHLVL is 1?

I assume you have a long running script and are wanting to prevent a second copy from starting if the first is running. What is probably happening is that your test is seeing 'itself' in the output from ps and is claiming that another copy is already running.

When I have to ensure that the invocation of a script is the only one running I use a marker directory in /tmp. Only one process can create a directory, so if two are started at the same time then only one will 'win' and continue running. Further, I add some information to the directory so that when another detects one already running, it can verify that it is still running and allows itself to start if it finds a marker, but doesn't find an associated process.

Here's an example:

#!/usr/bin/env ksh

trap "rm -fr \${solo_mark:-nosuchfile}" EXIT            # remove our marker stuff at exit

cmd=${0##*/}
solo_mark=/tmp/$cmd.solo
if ! mkdir $solo_mark 2>/dev/null       # if two started at the same time only one will be successful
then
    sleep 1                             # if there was a collision, allow winner to set the info file
    read rinfo <$solo_mark/info
    echo "verification that '$rinfo' is still running"
    if ps -e -o pid,command |awk -v rinfo="$rinfo" '
        BEGIN { split( rinfo, a, " " ); }
        $1 == a[1] {
            if( rinfo == $0 )
                exit( 1 );
            next;
          }'
    then
        echo "marker exists, but not running; we continue"
    else
        echo "already running"
        exit 1;
    fi
else
    echo "not running"
fi
ps -o pid,command | grep "^[ ]*$$" >$solo_mark/info     # save our info for others to verify
 


# ------- do intended work here -----------------


 
 

The bit of extra work to save the info, and verify it, makes things easier following a system crash, or someone killing the process in such a way that the marker doesn't get removed.

Hope this helps.

Thanks for the help, but as you said, the problem with the 'test&set' method is the reinit after system crash or manual killing.
My problem is that I see 2 lines, the shell process id and it's parent, I must be able to make the difference between the parent and an other process.
What I dont understand also is that i do it on 2 different machines and I get 2 differents outputs.
On the 1rst machine (spark v210) I get
root 14550 14543 0 10:40:48 pts/2 0:00 /usr/bin/ksh test.sh
root 14543 14016 0 10:40:45 pts/2 0:00 /usr/bin/ksh test.sh
As you can see these 2 lines are in fact related to the same process, the first line is in fact the parent process of the process appearing in the 2nd line.
the real solution is to store the PID and the PPID in 2 different arrays and build an algorythm that will be able to understand this situation.
On the second machine (spark v120) i get a single line.
I think that it is because that the first one got 2 processors and the 2nd one a single processor.

---------- Post updated at 12:48 PM ---------- Previous update was at 11:24 AM ----------

I think I got something :
here is how to manage the 'Parent process' case

set -A pids Dum
set -A fpids Dum
ps -ef| grep $0 | grep -v grep > $LOGDIR/$0.pid

i=0
j=0
while read filename
do
  pids=$(echo $filename | awk '{printf "%s ",$2}') # I store the pid
  fpids=$(echo $filename | awk '{printf "%s ",$3}') # I store the parent pid
#  echo "pids fpids index $i =" ${pids} ${fpids}

  (( i=i+1 ))
done < $LOGDIR/$0.pid

while [[ $j -lt $i ]]
do
if [[ ${pids[$j]} -ne $$ ]] # if the considered pid is not me
thenif [[ ${fpids[$j]} -ne $$ ]] # and even not my parent
thenprint " $0 is already running. Exiting" #well it is a stranger
exit 0fifi
(( j=j+1 ))
done

Actually, I said that the bit of extra work was to handle that situation so that it wasn't a problem. With the example I posted restart is clean following a crash or kill without any manual effort to clean up.