Not running a cron job when the prev run was not finished
How can I block a cron job when the previous run was not finished. Its a cron job which is running every 5 minutes, but sometimes it needs more than 5 minutes to run.
Edit The script which is called, crashes sometimes! So it can not delete lock file.
Use flock(1)
:
NAME
flock - manage locks from shell scripts
SYNOPSIS
flock [options] <file> -c <command>
flock [options] <directory> -c <command>
flock [options] <file descriptor number>
[...]
You can have it block or immediately exit. Pre-existence (or absence) of the lock file doesn't make a difference. It creates the file if needed and uses a flock()
system call to lock the file. This lock is automatically released at process death.
For example, in cron:
*/5 * * * * /usr/bin/flock /tmp/my.lock /usr/local/bin/myjob
If your jobs don't always finish in 5 minutes, you might consider using --timeout
so that your jobs don't queue up:
flock --timeout=300
Or use --nonblock
to exit immediately -- it would be similar to --timeout=0
If your script is a shell script, you can use some clever redirection tricks to use flock within your script itself:
(
flock -n 9 || exit 1
# ... commands executed under lock ...
) 9>/var/lock/mylockfile
Or, the manual also suggests making your script recursive by putting this at the top (it uses the script itself as its lock file):
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
See the flock(1)
man page for more information
Pid files are the way to go, however, much like init scripts don't just give up when they see a pid file, you should check to ensure that the pid in the file still exists.
Something like this would do the trick:
PIDFILE=/var/run/myscript.pid
if [ -e "$PIDFILE" ] ; then
# our pidfile exists, let's make sure the process is still running though
PID=`/bin/cat "$PIDFILE"`
if /bin/kill -0 "$PID" > /dev/null 2>&1 ; then
# indeed it is, i'm outta here!
/bin/echo 'The script is still running, forget it!'
exit 0
fi
fi
# create or update the pidfile
/bin/echo "$$" > $PIDFILE
... do stuff ...
/bin/rm -f "$PIDFILE"