Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I wrote a shell script run_script.sh, which includes a step which creates an empty file run_script.lck. Everytime the shell script was called by the cronjob, it will check for the existence of run_script.lck. If the lock is presence, it indicates that run_script.sh is already running and hasn't finished yet. The run_script.lck file will be deleted in the end of the program.

The trouble is to remove the lock file when the shell script crashed and before it exits.

I wrote a line like this:

trap "rm -f run_script.lck" EXIT

But it will remove the lock file in an undesired condition like this:

I execute run_script.sh in shell A, and it is running, the lock file was created. Then I execute it again in shell B, and it said that the script is already running and the script will be aborted. However, because the trap received an EXIT signal including the signal from shell B, which is exiting an aborted script, then it removes the lock file. And the script in shell A is still running, but the lock was deleted and anyone can call another run_script.sh again while there is already one script running.

Any idea how to solve this?

share|improve this question

migrated from stackoverflow.com Sep 21 '11 at 6:38

This question came from our site for professional and enthusiast programmers.

add comment

3 Answers

up vote 4 down vote accepted

To illustrate Ignacio's answer (use following protocol: first check if lockfile exists and then install the trap), you can solve the problem like this:

$ cat test2.sh
if [ -f run_script.lck ]; then
  echo Script $0 already running
  exit 1
fi
trap "rm -f run_script.lck" EXIT
# rest of the script ...
share|improve this answer
add comment

Check for presence of the lock before setting the trap.

share|improve this answer
    
Finally we still need to set the trap and it will exit. –  lamwaiman1988 Sep 21 '11 at 2:08
add comment

On way is set the trap on errors and let sh abort the script in case of errors (set -e). For example

$ cat test.sh
set -e
trap "echo foo" ERR
if [ $# == 1 ]; then
  exit 0
fi
false
$ bash test.sh
foo
$ bash test.sh 1
$

(where $# is the number of arguments)

In your script you just have to make sure that you execute your trap command when the script runs successfully (i.e. no crash happens, e.g. at the end of your normal program-flow).

set -e means that each exit status unequal 0 ends the execution of the script. Similar to that, with set -u every (probably accidental) use of an undefined variable ends the execution.

Thus, transferring this idea to the original use case, a solution could look like this:

$ cat test.sh
set -e
trap "rm -f run_script.lck" ERR
if [ -f run_script.lck ]; then
  echo Script $0 is already running
  exit 1
fi
#
# do all the work ...
#
# no error until now
rm -f run_script.lck
share|improve this answer
    
what does the if statement do? –  lamwaiman1988 Sep 21 '11 at 16:53
    
@gunbuster363, it checks if one argument is supplied. In your use case you would check the existence of the lock-file. I updated the answer with another example. –  maxschlepzig Sep 22 '11 at 8:52
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.