tags:

views:

387

answers:

7

I have a bash script I want to run every 5 minutes from cron... but there's a chance the previous run of the script isn't done yet... in this case, i want the new run to just exit. I don't want to rely on just a lock file in /tmp.. I want to make sure sure the process is actually running before i honor the lock file (or whatever)...

Here is what I have stolen from the internet so far... how do i smarten it up a bit? or is there a completely different way that's better?

if [ -f /tmp/mylockFile ] ; then
  echo 'Script is still running'
else
  echo 1 > /tmp/mylockFile
  /* Do some stuff */
  rm -f /tmp/mylockFile
fi
+3  A: 

If you want to check the process's existence, just look at the output of

ps aux | grep your_script_name

If it's there, it's not dead...

As pointed out in the comments and other answers, using the PID stored in the lockfile is much safer and is the standard approach most apps take. I just do this because it's convenient and I almost never see the corner cases (e.g. editing the file when the cron executes) in practice.

ire_and_curses
In addition, you can store the PID of the current BASH process in that lock file. BASH provides a variable '$$' (minus the quotes) that gives that number. See here: http://tldp.org/LDP/abs/html/internalvariables.html for some of those variables
Buggabill
-1 What if "emacs your_script_name" is one of the processes running?
mobrule
You're both absolutely right. The PID stored in the file would be a much better way to go. I just tend to do it this way because I'm lazy, my scripts aren't mission-critical, and it usually works (pretty rare that I would actually be editing the script when the cron executes).
ire_and_curses
+3  A: 

Store your pid in mylockFile. When you need to check, look up ps for the process with the pid you read from file. If it exists, your script is running.

Pavel Shved
A: 

You can always just:

 if ps -e -o cmd | grep scriptname > /dev/null; then 
     exit
 fi

But I like the lockfile myself, so I wouldn't do this without the lock file as well.

Kyle Brandt
Depending on how portable this needs to be, you might need to tweak your ps options, and you might be able to add -q to grep instead of the /dev/null
Kyle Brandt
Not co-worker proof enough: someone might be running "less scriptname" and that would be enough to prevent the script from running
mobrule
mobrule: Ya, never thought of that, just because I would never do it this way ;-) The lockfile is better.
Kyle Brandt
+2  A: 
lf=/tmp/pidLockFile
cat /dev/null >> $lf
read lastPID < $lf
[ ! -z "$lastPID" -a -d /proc/$lastPID ] && exit
echo not running
echo $$ > $lf
sleep 5
DigitalRoss
Why `cat /dev/null >> $lf` instead of `touch $lf`? Why `sleep` when there's no loop?
Dennis Williamson
`touch(1)` is good too. The sleep is just for demonstration, to make my script fragment testable on its own.
DigitalRoss
(That is, the pid will vanish as soon as that script ends)
DigitalRoss
+2  A: 

You might want to have a look at the man page for the flock command, if you're lucky enough to get it on your distribution.

NAME
       flock - Manage locks from shell scripts
SYNOPSIS
       flock [-sxon] [-w timeout] lockfile [-c] command...
kali
+1  A: 

In some cases, you might want to be able to distinguish between who is running the script and allow some concurrency but not all. In that case, you can use per-user, per-tty or cron-specific locks.

You can use environment variables such as $USER or the output of a program such as tty to create the filename. For cron, you can set a variable in the crontab file and test for it in your script.

Dennis Williamson
+2  A: 

Never use a lock file always use a lock directory. In your specific case, it's not so important because the start of the script is scheduled in 5min intervals. But if you ever reuse this code for a webserver cgi-script you are toast.

if mkdir /tmp/my_lock_dir 2>/dev/null
then
   echo "running now the script"
   sleep 10
   rmdir /tmp/my_lock_dir
fi

This has a problem if you have a stale lock, means the lock is there but no associated process. Your cron will never run.

Why use a directory? Because mkdir is an atomic operation. Only one process at a time can create a directory, all other processes get an error. This even works across shared filesystems and probably even between different OS types.

Gunstick