Is it possible to schedule a cron job to run fortnightly?

Is there a way to schedule a cron job to run every fortnight?

(One way I can think of, within crontab, would be to add two entries for “date-of-month”…)

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

No, cron only knows about the day of the week, the day of the month and the month.

Running a command twice a month on fixed days (e.g. the 1st and the 16th) is easy:

42 4 1,16 * *  do_stuff

Running a command every other week is another matter. The best you can do is to run a command every week, and make it do nothing every other week. On Linux, you can divide the number of seconds since the epoch (date +%s) by the number of seconds in a week to get a number that flips parity every week. Note that in a crontab, % needs to be escaped (cron turns % into newlines before executing the command).

42 4 * * 1  case $(($(date +%s) / (60*60*24*7))) in *[02468]) do_stuff;; esac

Method 2

You cannot directly have cron run a job fortnightly (every two weeks). However, it is reasonably straightforward to ensure that the main part of the job runs only every other week. @Gilles has offered one solution; here’s another:

42 4 * * 1    test 1 -eq $(($(date +%g) & 1)) && do_stuff...

The date +%g command returns the current week number (of the year), and this is bitwise ANDed to return either 1 or 0 before being used to determine whether the real job can be run.

The same caveat on the percent symbol %: in a crontab entry it must be escaped to prevent cron treating it specially.

Method 3

I know I’m late to the party but, everyone wants a solution or three to any problem…

I found this post while wanting to do the same thing as the OP, except for a Sunday.

@user140906 has a valid concern, which can be observed when running this snippet;

for n in $(seq 17 33); do ncal -A1 -bw dec 20${n}; done

Which initially seems to repeat every 6 years – I didn’t check them all! 🙂

I then found this link which offers two solutions, one similar to @gilles-so-stop-being-evil, that should work, the most obvious one is below;

#!/bin/bash

# a file marking the state on disk
mark_file=$HOME/.job-run-marker-1

# check whether the job run last time it is invoked
if [ -e $mark_file ] ; then
  rm -f $mark_file
else
  touch $mark_file
  exit 0
fi

# job command is here

Coupled with a crontab entry like;

0 2 * * 2 my_script

Easily adapted to be used for multiple crontab entries (pass a value for mark_file or an ID instead of hard-coding it), or expand the same logic with some grep / awk / sed magic, to add/remove/append lines in a file that represent the ID and status/date of each job execution.

Either way, hopefully that helps someone, perhaps even a future me!


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x