13

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

I've set up a cronjob to backup my folders properly which I am quite proud of. However I've found out, by looking at the results from the backups, that my backup script has been called more than once by Crontab, resulting in multiple backups running at the same time.

Is there any way I can ensure that a certain shell script to not run if the very same script already is executing?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Industrial
  • 41,400
  • 69
  • 194
  • 289

4 Answers4

35

A solution without race condition or early exit problems is to use a lock file. The flock utility handles this very well and can be used like this:

flock -n /var/run/your.lockfile -c /your/script

It will return immediately with a non 0 status if the script is already running.

Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
7

The usual and simple way to do this is to put something like:

if [[ -f /tmp/myscript.running ]] ; then
    exit
fi
touch /tmp/myscript.running

at the top of you script and

rm -f /tmp/myscript.running

at the end, and in trap functions in case it doesn't reach the end.

This still has a few potential problems (such as a race condition at the top) but will do for the vast majority of cases.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • this will prevent the script from running if it was even run before. – unbeli Jan 22 '11 at 16:05
  • @unbeli: no it won't, because you remove the sentinel file on exit. – paxdiablo Jan 22 '11 at 16:05
  • 9
    There's a race condition because of the TOCTOU (time of check, time of use) between 'the file does not exist' and 'create the file'. The atomic mechanism is `mkdir /tmp/myscript.running 2>/dev/null`. If the directory exists, the `mkdir` will fail, and the kernel ensures that only one of concurrently running `mkdir` commands (system calls) succeeds. – Jonathan Leffler Jan 22 '11 at 16:27
  • rm wasn't there when I commented. Anyway, this solution is far from the best. – unbeli Jan 22 '11 at 16:35
  • what if script crashes / gets killed / reboot happens while it's runing? script would never run again. Okay, reboot will clear /tmp, but you get the point. – galets Apr 23 '14 at 22:05
  • @galets, the trap will handle normal errors but you cannot protect against everything (like kill -9 or the power being pulled out). There will always be cases where intervention may be required no matter the method. The idea is to minimise that. – paxdiablo Apr 23 '14 at 22:49
  • @paxdiablo not to digress the conversation, but yes, that specific scenario you can and must protect from. It's actually very easy. All you need to do is create a file and open an exclusive lock on it. If process terminates for any reason, kernel will free the lock for you. This is exactly why flock is by far better solution. I agree you cannot protect from EVERYTHING, but something that's doable and easy - you should – galets Apr 25 '14 at 19:10
5

A good way without a lock file:

ps | grep $0 | grep -v grep > /var/tmp/$0.pid
pids=$(cat /var/tmp/$0.pid | cut -d ' ' -f 1)
for pid in $pids
do
   if [ $pid -ne $$ ]; then
      logprint " $0 is already running. Exiting"
      exit 7
   fi
done
rm -f /var/tmp/$0.pid

This does it without a lock file, which is cool. ps into a temp file, scrape the first field (pid #) and look for ourselves. If we find a different one, then somebody's already running. The grep $0 is to shorten the list to just those instances of this program, and the grep -v grep gets rid of the line that is the grep itself:)

David Hall
  • 51
  • 1
  • 1
0

You can use a tmp file.
Named it tmpCronBkp.a, tmpCronBkp.b, tmpCronBkp.c... etc. Releated of yout backup script.

Create it on script start and delete it at the end...

In a while, check if file exist or not and what file exist.

Have you tried this way?

elp
  • 8,021
  • 7
  • 61
  • 120
  • I am not sure if I made myself completely clear, but I want to ensure that my shell script isnt executed again, if it's already called by CRON and active – Industrial Jan 22 '11 at 16:03
  • Let this file hold PID of the started process. So you'll be able to figure out is it running at all. – akond Jan 22 '11 at 16:04
  • yes, you can check the tmp file and exit from scrit if file exist! – elp Jan 22 '11 at 16:07