If condition is true, sleep the cron job for 5 minutes

I have a script set to run after every minute. But in the script we have mentioned, if a condition is true, the script has to sleep for 5 minutes. How could this affect the crontab? Will the script be in sleep mode for 5 min, or it will run again as it set in crontab for every 1min?


You have two option to gain this. Normally cron doesn't matter whether the previous instance of the job is still running.

Option 1:

Write a lock file in the beginning of the script and delete it when it's finished. Then a check at the start of the script looks if the file exists, and if yes, the script ends without doing something. That could for example look like this:

# if the file exists (`-e`) end the script:
[ -e "/var/lock/myscript.pid" ] && exit

# if not create the file:
touch /var/lock/myscript.pid

...
# do whatever the script does.
# if condition
sleep 300 # wait 5 min
...

# remove the file when the script finishes:
rm /var/lock/myscript.pid

Option 2:

There is also a utillity for this. It's called run-one. From the manpage:

run-one - run just one instance at a time of some command and unique set of arguments (useful for cronjobs, eg)

The cronjob could then look like this:

* * * * *   /usr/bin/run-one /path/to/myscript

I've done similar - pausing a script if something happened, but I didn't run it from cron. Instead, I had a shell script that would continually re-run itself. In my case, I checked the load average, and paused for a minute if it was 'too high'. It it was OK, I did the things I needed to and then paused for a far shorter time.

This also has the twin advantages of there will only ever be one script running, and you can also re-run it more often than every minute, which is the minimum cron frequency.

#!/bin/bash

i_should_sleep() {
  if [ *condition* ]
  then
    return 0
  else
    return 1
  fi
}

if i_should_sleep; then
    sleep 300
    exec $0 $@
fi

nice COMMAND # run the action we really want to do

sleep 60  # or less than a minute, to run more often

exec $0 $@

To start it, you would create an Upstart or init.d job, or something similar.


With crontab, you can't do this, but you can do this with a little bit of extension of your script. I am thinking around the following pseudo-code:

#!/bin/bash
if ...temporary_file_exists
then
  if ...tmp_is_older_as_5_minute...
  then
     delete tmp
  else
     exit
  fi
fi

...
if "${condition}"
then
  touch $temporary_file
  exit
fi

...normal behavior of your script...

What it does? The main problem of the cron scripts, that you can't have easily a persistent memory between their runs. You need to do that always with ad hoc methods. In the unix scripting world, temporary files are very common solutions for that, and you use the existence (and the change time) of a temporary file to know, what is the actual situation.