Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'd like to run a job from cron at 8.30 on the first Monday of every month. The cron Wikipedia page says

While normally the job is executed when the time/date specification fields all match the current time and date, there is one exception: if both "day of month" and "day of week" are restricted (not "*"), then either the "day of month" field (3) or the "day of week" field (5) must match the current day.

(my emphasis)

Does that mean I can't do the first Monday of the month, I can only do the first (or whatever) day of the month? I can't think of a way round it.

share|improve this question
slhck - that sounds like a good solution - would you mind expanding it into an answer with the full code? then i'll mark it as correct :) – Max Williams May 28 '12 at 8:51
up vote 16 down vote accepted

You can put the condition into the actual crontab command:

[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"

Now, if this condition is true on one of the first seven days in a month, you have its first Monday. Note that in the crontab, the percent-syntax needs to be escaped though:

0   12  1-7 *   *   [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"

Replace the echo command with the actual command you want to run. I found a similar approach too.

share|improve this answer
nice one, thanks :) – Max Williams May 28 '12 at 9:54
actually, slhck, i spoke too soon - this isn't working in my crontab: it seems to have a problem with the date test for some reason. This works in the command line [ "$(date '+%a')" = "Mon" ] && echo "It's Monday" as does [ $(date '+%a') = "Mon" ] && echo "It's Monday" But, in the crontab it seems to be failing at this test. I can't get at any useful feedback from cron either: i'm trying this [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1 to capture any error output into a log but that's not working either :/ – Max Williams May 29 '12 at 8:53
Hm. Can you check whether the date output is correct? For example, just let a cron command run that outputs this to a file: date '+%a' > ~/datetest 2>&1 – then check if that resulted in the right string to compare against. – slhck May 29 '12 at 8:58
I found the problem - the percent in +%a needed escaping when it was in the crontab, ie the line needed to be this: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". If you could update your answer with that it would be helpful to future readers :) Thanks again - max – Max Williams May 29 '12 at 9:33
Oh, now I see why. Glad it works now, thanks for trying it out! – slhck May 29 '12 at 9:35

I have scheduled a job to run on the 4th Monday of every month at 4:00 PM as follows:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt
share|improve this answer

As far as I know it is NOT possible using only crontab, however one can use a wrapper function to pick the correct day from a "first seven days of month" contab entry; see this from entry.

The wrapper script would be

#! /usr/bin/ksh
day=$(date +%d)
if ((day <= 7)) ; then
   exec somecommand
exit 1

and you would need to run it (assuming it is called and globally available) using the crontab entry

0 0 * * 1
share|improve this answer
thanks elemaki. I thought about a similar solution using some extra code inside the task that gets run, getting it to test whether it's the first monday of the month inside the script, and then calling it every monday in crontab. It's a ruby script so it's easy to test the day of th week. But i was hoping there'd be a crontab only way. – Max Williams May 25 '12 at 15:56

I find it easier when there's no need to handle day numbers.

Run First Monday of month:

0 2 * * 1 [ `date '+\%m'` == `date '+\%m' -d "1 week ago"` ] || /path/to/command

i.e. if the month 1 week ago is not the same as the current month then we are on the 1st day 1 (= Monday) of the month.

Similarly, for the Third Friday

0 2 * * 6 [ `date '+\%m'` == `date '+\%m' -d "3 weeks ago"` ] || /path/to/command

i.e. if the month 3 weeks ago is different to current month then we are on the 3rd day 6 (= Friday) of the month

share|improve this answer

I made a general solution for this kind of problems, it works for first, second, third..... last weekday of the month.

You can use it like this:

30 06 * * Mon run-if-today 1 "Mon" && echo "First Monday"
30 06 * * Thu run-if-today 3 "Thu" && echo "Third Thursday"
30 06 * * Sun run-if-today L "Sun" && echo "Last Sunday"

The script run-if-today check for both the weekday and the desired week date range, if both match then it returns 0, otherwise 1.

Check the code here.

share|improve this answer

I believe this solves the problem more elegantly:

30 8 1-7 * 1 /run/your/
share|improve this answer
Doh! : "If both fields are restricted (ie, aren't *), the command will be run when either field matches the current time." – symcbean Jul 10 '14 at 8:35

On Solaris 10 I had to format the condition as follows:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"
share|improve this answer

You can try running cronjob for first seven days of month and let it execute only on Monday.

30 8 * * 1 [`date +\%d` -le 07] && <job>

Above should work for you.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.