3

How can a bash script ensure that not more than one copy of it is running?

I have tried:

ps -ef| grep /user/loca/shell/sh | wc -l

This shows me 2 because of the grep command. Change it to:

ps -ef | grep /user/loca/shell/sh | grep -v 'grep' wc -l 

then its shows 1. However, if I then vim /user/loca/shell/sh and then execute:

ps -ef| grep /user/loca/shell/sh | grep -v 'grep' wc -l

that shows 2. But there is only one process, I have started.

How can the bash script check whether the process is running?

Charles
51.5k13 gold badges107 silver badges146 bronze badges
asked Sep 9, 2011 at 15:27
5
  • Is /user/loca/shell/sh a script or a compiled executable? I suspect that you need to search the ps output more carefully. Please show the ps output when you're both running and editing. Commented Sep 9, 2011 at 15:33
  • yes , they are running and executable ... Commented Sep 9, 2011 at 15:35
  • $ ps -ef | grep '/user/loca/shell/sh ' root 30915 30891 0 15:19 pts/3 00:00:00 vim /user/loca/shell/sh joe 30956 30927 0 15:21 pts/5 00:00:00 grep /user/loca/shell/sh Commented Sep 9, 2011 at 15:45
  • adding that to the question would make it easier to read, however you don't appear to be actually running the program in that example. Commented Sep 9, 2011 at 15:54
  • Note that if I run bash /user/loca/shell/sh or bash -c /user/loca/shell/sh, then it is nigh on impossible to spot the difference between that and vim /user/loca/shell/sh or diff -c /user/loca/shell/sh /user/loca/shell/new.sh. Not to mention cp /user/loca/shell/sh xyz; ./xyz. Hence the 'lock file' approach. Commented Sep 9, 2011 at 16:04

3 Answers 3

7

The idiom often used in Unix Daemons is to create a file with the PID in it when they start.

Then you can check the existence and/or content of the file when you start, if it's there, you exit and leave that instance running.

At the end of the script you delete the file, ready to run next time.

The only problem comes when the script runs, but does not complete for some reason, leaving the PID file in existence. This can be taken care of by checking its timestamp, if it's too long ago, you assume that it was an aborted run and continue with the current one.

answered Sep 9, 2011 at 15:41
Sign up to request clarification or add additional context in comments.

4 Comments

To delete the file use trap "rm $PID_FILE" EXIT
Instead of the unreliable pid file timestamp method, better to check if the pid is in use and match the script name.
Also, the daemon can check whether the process recorded in the PID file is still extant. The kill -0 PID 2>/dev/null command will report success if the process PID exists, and failure if not.
On most modern unix variants there is a /proc filesystem with directories or files for every currently running process. Rather than writing the pid into a file, make the pid file a symlink to the pid file in /proc, then to check if the program is still running see if the file is a broken symlink (test -h pidfile -a ! -e pidfile == broken symlink)
0

Try pgrep instead of 'ps -ef ...' in your script:

pgrep /usr/loca/shell/sh

If that won't work then I'd resort to locking by attempting to create a symbolic link from the script if one does not exist yet and bail out if it already exists, and deleting it upon exit. Creating symbolic link is an atomic operation on unix that can be used as sort of a poorman's lock for shell scripts.

answered Sep 9, 2011 at 15:51

Comments

0

I use a file lock:

MY_LOCK_FILE='whatever.lock'
( if (flock -nx 200); then
 # Do stuff here...
 fi
) 200>"$MY_LOCK_FILE"
answered Sep 9, 2011 at 22:59

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.