mtk
mtk

Reputation: 13717

cron expression for every > 60 minutes job

Is there any way to design the cron expression as to run every 70 minutes or 210 minutes i.e. > 60 minutes. I tried to search for this, but was not able to find this.

I finally went with a wrapper script that would do the required time checking which was called every 5 minutes(or the optimal recurring time).

How to accomplish such task in cron expression ?

Upvotes: 5

Views: 7339

Answers (3)

kvantour
kvantour

Reputation: 26491

This answer is fairly identical to this and this

If you want to run a cron every n minutes, there are two cases to consider :

  • Every nth minute (60 is divisible by n)
  • Every nth minute starting from YYYY-MM-DD HH:MM:00 (generic)

The later covers the OP's case, but to remain generic I present both cases.

Every nth minute (60 is divisible by n)

This is valid for (n=1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30)

For this we use the combination of defining a range and a step value:

man 5 crontab: Step values can be used in conjunction with ranges. Following a range with /<number> specifies skips of the number's value through the range. For example, 0-23/2 can be used in the 'hours' field to specify command execution for every other hour (the alternative in the V7 standard is 0,2,4,6,8,10,12,14,16,18,20,22). Step values are also permitted after an asterisk, so if specifying a job to be run every two hours, you can use */2.

See the following example:

# Example of job definition:
# .----------------- minute (0 - 59)
# |   .------------- hour (0 - 23)
# |   |  .---------- day of month (1 - 31)
# |   |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |   |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
# |   |  |  |  |
# *   *  *  *  *   command to be executed
  m/n *  *  *  *   command1

Here, command1 will be executed every nth minute from m till 59.

This means that :

  • if m<=n, they will always be spaced by n minutes. Eg. m=2,n=10 :: the job will run on minutes 2,12,22,32,42,52
  • if m>n, they will always be spaced by n minutes, except at the start of the hour. Eg. m=12,n=10 :: the job will run on minutes 12,22,32,42,52. So here we have a jump of 20 minutes between the 52nd and 12th minute.

note: you clearly see that if n does not divide 60 perfectly, you will have problems. Eg. m=0,n=11 runs on 0,11,22,33,44,55, so we only have 5 minutes to the next run.

Every nth minute starting from YYYY-MM-DDTHH:MM:00

If you want to run a cron every n minutes, you cannot do this cleanly with cron but it is possible. To do this you need to put a test in the cron where the test checks the time. This is best done when looking at the UNIX time stamp, the total seconds since 1970-01-01 00:00:00 UTC. Let's say we want to start from the moment McFly arrived in Riverdale:

% date -u -d '2015-10-21 07:28:00' +%s 
1445412480

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
# |  |  |  |  |
# *  *  *  *  *   command to be executed
  *  *  *  *  *   mintestcmd "2015-10-21 07:28:00"   7 && command1
*/10 *  *  *  *   mintestcmd "2015-10-21 07:00:00"  70 && command2
*/30 *  *  *  *   mintestcmd "2015-10-21 07:00:00" 210 && command3

with mintestcmd defined as

#!/usr/bin/env bash
starttime=$(date -d "$1" "+%s")
# return UTC time
now=$(date "+%s")
# get the amount of minutes
delta=$(( (now - starttime) / 60 ))
# set the modulo
modulo=$2
# do the test
(( delta >= 0 )) && (( delta % modulo == 0))

In the above examples we have:

  • command1 will run every 7 minutes on 2015-10-21 07:28:00, 2015-10-21 07:35:00, 2015-10-21 07:42:00, 2015-10-21 07:49:00, ...
  • command2 will run every 70 minutes from 2015-10-21 07:00:00 onwards. Since 70 is divisible by 10 and the start-time starts perfectly on the hour, we can set the cron to run every 10 minutes.
  • command3 will run every 210 minutes from 2015-10-21 07:00:00 onwards. Since 210 is divisible by 30 and the start-time starts perfectly on the hour, we can set the cron to run every 30 minutes.

Remark: UNIX time is given in UTC. If your cron runs in a different time-zone which is influenced by daylight saving time, it is advisable not to run the command between 2 and 3 o'clock. This could skip the command or run the command twice (depending upon whether the time jumps forward or backwards)

Remark: UNIX time is not influenced by leap seconds

Remark: cron has no sub-second accuracy

Upvotes: 0

Sun
Sun

Reputation: 2715

Run every 70 minutes

* */1.1666

or

Run every 210 minutes

* */3.5

Upvotes: 1

VonC
VonC

Reputation: 1326852

Basically, you need to run your cron every minute:

* * * * *

and let your script determine if its last execution dates from 70 or 210 minutes ago.
If it does, it would go on with the rest of the script.
If it does not, it would exit immediately.

In other words, don't try and put everything in the cron expression.

As commented by Keith Thompson, you could instead run that script less often (0 0/5 0 ? * * *), with a test at 70 minutes, or every 30 minutes (0 0/30 0 ? * * *) with a test at 210 minutes.

Upvotes: 0

Related Questions