2

I have an entry in my crontab file:

14 17 * * */2 python /home/pi/scripts/irrigate_5mins.py >/dev/null 2>&1

The intention is to run the command every other day, which is what the manpage (man 5 crontab) says is what */2 does. The actual quote from the manpage is:

Steps are also permitted after an asterisk, so if you want to say ``every two hours'', just use ``*/2''

The actual behaviour is that the command runs with a recurrence pattern of 2, 2, 2, 1, 2, 2, 2, 1 and so on. So, for example, in March / April the command ran on 15th, 17th, 18th, 20th, 22nd, 24th, 25th, 27th, 29th, 31st, 1st April, 3rd, 5th, 7th, 8th, 10th, 12th, where the dates in bold are those where the command was run the previous day.

So my question is: why is it behaving like this, and is there an (easy) way I can make it do what is expected?

System info:

root@pi:~# uname -a
Linux pi 4.9.28+ #998 Mon May 15 16:50:35 BST 2017 armv6l GNU/Linux
root@pi:~# lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 8.0 (jessie)
Release:        8.0
Codename:       jessie

It may or may not be of relevance that the system is connected to a timer which causes a hard reboot every 24 hours.

2

By specifying */2 in the day-of-week field, you run on even days. Even days of the week are Mondays, Wednesdays, Fridays and Sundays. (Actually, these are the odd days, hmm, still...)

If you want to run the job on slightly more regular intervals, use the day-of-month field instead (the third field). Note that on months with an odd number of days, this will cause the job to instead skip one day when the next month starts: ..., 28th, 30th, (not on the 31st, not on the 1st), 2nd, 4th, etc.

You could work around this by adding a schedule for months with even days and a separate schedule for months with an odd number of days (although I haven't really thought that through properly to know whether that would make it match up properly).

Another possibility would be to have the job schedule itself using at instead of using cron. This would definitely be a more "hackish" solution and would possibly fail if the job terminated abnormally between starting to run and successfully rescheduling itself in two days time, or if the system happened to be down at the next scheduled run.

  • You'd need to separate the months based on how many odd months there are in a year preceding that month. And it would still skip when the year changes, since most years have an odd number of days – ilkkachu May 28 '18 at 10:38
  • 1
    */2 would run on days 0,2,4,6: Sunday, Tues, Thu, Sat – glenn jackman May 28 '18 at 18:28
  • @glennjackman Yes. So assuming the reported days refers to this year (2018), they are a bit strange. – Kusalananda May 28 '18 at 18:54
  • Test the cron definition string here Just paste 14 17 * * */2 and click test to see a list of the next executions. – Isaac May 29 '18 at 12:23
1

I would schedule the cron job to run every day. Then the script can decide if the day-of-year is an even number: if not, exit.

import datetime
today = datetime.date.today()
doy = int(today.strftime("%j"))
if (doy % 2 == 1): exit()
... 
  • Note that it would still call the script two days in a row in non-bissextile years (on the 31st of December and the day after). – Stéphane Chazelas May 28 '18 at 23:59
  • True. One could use days since some point in time, or something like ((day of year mod 2 plus year mod 2) mod 2) – glenn jackman May 29 '18 at 1:24

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.