If you want to run a cron every n
minutes, there are two cases to consider :
- Every
n
th minute (60 is divisible by n
)
- Every
n
th minute starting from minute YYYY-MM-DD HH:MM:00
(generic)
The latter case is a generic case and covers the case where 60 is not divisible by n
. It is mentioned that this case needs a "begin-time". With some simple math, you quickly figure why this is.
Every n
th minute (60 is divisible by n
)
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 examples:
# 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 52
nd 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 and not 11.
Every n
th minute starting from minute YYYY-MM-DD HH:MM:00
This case is generic and covers the non-divisibility of 60.
Here it gets more interesting and a different approach needs to be made. This can be resolved when you have a continuous counter from a given day. Enter 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 -d '2015-10-21 07:28:00' +%s
1445412480
For a cronjob to run every 7
th minute after `2015-10-21 07:28:00', the crontab would look like this:
# 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 && command2
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 % modulo == 0))
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 if the time jumps forward or backwards)
Remark: UNIX time is not influenced by leap seconds
Remark: cron
has no sub-second accuracy