What's the cron (linux) syntax to have a job run on the 2nd and 4th Saturday of the month?
5 Answers
The second Saturday of the month falls on one (and only one) of the dates from the 8th to the 14th inclusive. Likewise, the fourth Saturday falls on one date between the 22nd and the 28th inclusive.
You may think that you could use the day of week field to limit it to Saturdays (the 6
in the line below):
0 1 8-14,22-28 * 6 /path/to/myscript
Unfortunately, the day-of-month and day-of-week is an OR proposition where either will cause the job to run, as per the manpage:
Commands are executed by
cron
when the minute, hour, and month of year fields match the current time, and when at least one of the two day fields (day of month, or day of week) match the current time.The day of a command's execution can be specified by two fields - day of month, and day of week. If both fields are restricted (i.e., aren't *), the command will be run when either field matches the current time. For example,
30 4 1,15 * 5
would cause a command to be run at 4:30 am on the 1st and 15th of each month, plus every Friday.
Hence you need to set up your cron
job to run on every one of those days and immediately exit if it's not Saturday.
The cron
entry is thus:
0 1 8-14,22-28 * * /path/to/myscript
(to run at 1am on each possible day).
Then, at the top of /path/to/myscript
, put:
# Exit unless Saturday
if [[ $(date +%u) -ne 6 ]] ; then
exit
fi
And, if you can't modify the script (e.g., if it's a program), simply write a script containing only that check and a call to that program, and run that from cron
instead.
You can also put the test for Saturday into the crontab
file itself to keep the scheduling data all in one place:
0 1 8-14,22-28 * * [ `date +\%u` = 6 ] && /path/to/myscript
-
Just wondering, what will * * * * 6/2
do ? – chochim Jul 27 '12 at 09:56 -
@chochim, from what I remember, skips are only useful with ranges (such as 1-5/2 for 1,3,5). If you apply them to a single value, it's the same as just using the single value. You're _almost_ there in that you could use the day-of-month as 1-31/14 but that'll give you 1,15 and hence won't guarantee it's a Saturday. – paxdiablo Jul 27 '12 at 11:18
-
`0 1 1-7,15-21 6 /path/to/myscript` should be `0 1 1-7,15-21 * 6 /path/to/myscript`. Missing the month entry. Otherwise helpful answer! – bigtex777 May 28 '16 at 00:20
Expanding on @paxdiablo's reply, why not just put the addition into the crontab, instead of the script?
#m h dom mon dow command
0 1 8-14,22-28 * * [ `date +\%u` = 6 ] && /path/to/myscript
Note the backslash before %u, which is not needed when you try this on the command line, but it is needed in a crontab entry to ensure the shell gets to see the whole command.
Doing it this way puts all the logic for selecting the proper day in the place your colleagues first look at, and you can run the script manually on another day if the need arises.

- 618
- 8
- 11
What about having two jobs
0 0 0 ? * 7#2
0 0 0 ? * 7#4
The first one gives
2015-12-12 00:00:00 (-08:00)
2016-01-09 00:00:00 (-08:00)
2016-02-13 00:00:00 (-08:00)
2016-03-12 00:00:00 (-08:00)
2016-04-09 00:00:00 (-07:00)
And the second one gives
2015-11-28 00:00:00 (-08:00)
2015-12-26 00:00:00 (-08:00)
2016-01-23 00:00:00 (-08:00)
2016-02-27 00:00:00 (-08:00)
2016-03-26 00:00:00 (-07:00)

- 315
- 2
- 6
If you have it availble, you can use ncal to to get a calendar with day names along the side in the first column where you can grep for the day of the week in order to get the dates of the month of which that day falls on:
August 2012 Su 5 12 19 26 Mo 6 13 20 27 Tu 7 14 21 28 We 1 8 15 22 29 Th 2 9 16 23 30 Fr 3 10 17 24 31 Sa 4 11 18 25
If you grep for "Sa" for Saturday, you'll get a line with the dates of the month that are Saturdays. If you use awk to parse out a particular column (awk '{print($3)}' for the "second" Saturday and awk '{print($5)}' for the fourth Saturday) and compare that to today's date (date +%e), then you'll know if the script needs to run or not.
You can then build a script around this and chain it together in a crontab entry that runs on Saturdays. So when it runs on a Saturday, if the date equals the 2nd or 4th Saturday, exit cleanly and then use && in the crontab entry after this script to run the actual job. But if it it is the 1st or 3rd Saturday, exit 1 and then && won't run the job. (You'll get a cron error email saying it did not complete or whatever)

- 11
- 1
The above solution works well. In addition, I had a more complicated challenge where I have multiple sets of scripts and each set depended on the other. The first set of scripts had to run on the 3rd Sunday of the month. The 2nd set of scripts on the Monday following the 3rd Sunday of the month, and so forth. The solution I came up with, building on the above solution, is the following:
3rd Sunday date 15-21.
Monday after 3rd Sunday date 16-22.
Tuesday after 3rd Sunday date 17-23.
The other date ranges are offset by the number of days difference from the first set of scripts, which are the triggering scripts.

- 11
- 1
-
1When configuring these date parameters in cron, I was reminded by testing rounds that the (day of month, month) and (day of week) operate on "or" logic. Thus, consider the example: 07 17 15-21 * 2 /home/user/scripts/execute_this.ksh this will execute on a day of month that is between 15-21 inclusive, OR on any Tuesday. So, it is best to leave the day of week as "*" especially since the conditional suggested for the script operates on the day of week condition. – Louie Labayen Jan 16 '14 at 18:10