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):

       flock - manage locks from shell scripts

       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:


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

 # create or update the pidfile
 /bin/echo "$$" > $PIDFILE

 ... do stuff ...

 /bin/rm -f "$PIDFILE"
  • +1 Yours is a good approach, but it's still possible (however rare) that the both the pidfile and the PID could exist but not be related. Instead of kill -0 you could do if [ "$(ps -p $PID o cmd=)" = "$scriptname" ] or if [ "$(pgrep "$scriptname")" = "$PID" ]. – Dennis Williamson Nov 9 '10 at 14:09

Checking for pid or lock file can fail when the cron job fails to clean the file after exit. I see the better option is to check for the process itself such as:

ps -ef | grep script_name | grep -v grep | wc -l

This will give you the number of processes that have the name 'script_name'. You can check this count at the beginning of your script execution.

  • Ok, this solution will work when the script crashes?! – powtac Nov 9 '10 at 13:22
  • pgrep is less likely to give false positives. Or you could use ps -e -o cmd= | grep "^$scriptname". – Dennis Williamson Nov 9 '10 at 14:14
  • Better yet is to wrap the first letter of the grep search term in square braces, such as 'ps ax | grep [f]oobar'. The process list will duplicate the braces, but will filter out on the grep as not matching the regex. – Magellan Jul 2 '14 at 5:47

You can't, cronjobs don't come with this functionality. Put something in your script to check for it, or have it create a file when finished and use something such as inotifywait to block.


Look for a file in e.g. /var/run. If the file is found then exit. Otherwise, create the file, run your routine, and then remove the file.


There are many ways. Popular one is to use a lock file.

1) When the script starts, it checks if a lock file (like /var/lock/powtac.loc) already presents.

2) If it does exist, script aborts, assuming the previous script is still running *).

3) If it does not exist, script creates the file and continues to do whatever it needs to do.

4) Upon exit, script deletes the lock file.

*) It would also be possible to check the process list at this point, search for matches for your cron job and if found, see when they were started. If recently, then assume they are still running, if loooooooooong time ago, then assume they were stuck.


I wouldn't have two cron jobs I'd have one.

* * * * * /some/command && /some/other/command

It will only run if the first command completes successfully, and only after it's done.

( note: if you need it to be a few minutes after use sleep )

  • question implies it's the same task but it sometimes takes longer than the delay to run. Doing it your way, he'd just have your command running every 10 minutes instead of his command twice every 5 minutes. – James L Nov 9 '10 at 13:13
  • bagh...then he's just running it too often, imo. I read it wrong... but I'm still leaving my answer. – xenoterracide Nov 9 '10 at 13:15
  • 1
    Not all cronjobs run in deterministic lengths of time, particularly ones like rsyncing from a mirror. – jgoldschrafe Nov 9 '10 at 13:35
  • @jgoldshrafe and you think rsyncing a mirror every 5 minutes is a good idea? nothing runs in a deterministic length of time, everything is variable – xenoterracide Nov 9 '10 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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