9

Today is Friday, October 3, 2014 3:58 AM

I want to schedule a cronjob like that to run it at the following dates:

  1. Saturday, October 4, 2014 8:00 AM
  2. Saturday, October 18, 2014 8:00 AM
  3. Saturday, November 1, 2014 8:00 AM ... ...

So every 2 weeks , on Saturday, at 8 o'clock.

23
0 8 * * 6 test $((10#$(date +\%W)\%2)) -eq 1 && yourCommand

date +%W: week number of year with Monday as first day of week, today week 39

10#$(date +%W): conver the date +W to decimal number and avoid shell base parsing confusion

$((39%2)): modulo operation: result is 0 (even week number) or 1 (odd week number), this week result is 1, next week 0

test 1 -eq 1: arithmetic test (equal), in this case result is boolean true

&& yourCommand: Boolean AND: run yourCommand only if result of previous command was boolean true

Note that the year can get two odd weeks: 53 (this year) and 1 (next year)

  • 2
    That's elegant! It still, as you've noted, has a corner-case on the 53rd Saturday of the year, which will happen roughly seventy years in every four centuries. – MadHatter Oct 3 '14 at 10:11
  • @Cyrus thank you for your answer, but if I write * * * * 5 test $(($(date +%W)%2)) -eq 1 && /u02/restore/scripts/test.sh the script does not run but if I write * * * * 5 /u02/restore/scripts/test.sh script runs. why is your expression not working? I was just testing the cases.And found that not working somehow. – kupa Oct 3 '14 at 12:32
  • 1
    My mistake. Cron interprets % as newline. Escape both % with a \ in your cronjob: 0 8 * * 6 test $(($(date +\%W)\%2)) -eq 1 && yourCommand – Cyrus Oct 3 '14 at 13:07
  • Sorry to bring back this old question but it wasn't working for me and when i try to execute $((10#$(date +%W)%2)) -eq 1 && echo OK my shell tries to execute the result of the week calculation : -bash: 1: command not found. Any clue why it's doing that ? Thanks. – jhuet Mar 31 '17 at 12:35
  • 2
    @jhuet: test is no user it‘s a command. Try: test $((10#$(date +\%W)%2)) -eq 1 && echo odd || echo even – Cyrus Mar 31 '17 at 18:23
4

What you've shown is "every week". Then the code is:

0 8 * * 6

Are you sure you need to run it every two weeks?

0 8 * * 6 expr `date +\%s` / 604800 \% 2 >/dev/null || yourCommand
  • 1
    Can you explain the command, please – kupa Oct 3 '14 at 9:39
  • 1
    It's better to use what Cyrus gave - $(($(date +%W)%2)) "W" stands for a week number the year. Starting from zero to 53. If it can be divided by two, then it's your "every second" week. So cronjob runs every week but the 'expr' executes command yourCommand only if week's number can be divided by 2. – Glueon Oct 3 '14 at 9:44
  • when I run test $(($(date +%W)%2)) -eq 1 on command line returns nothing, why? – kupa Oct 3 '14 at 9:52
  • 1
    just run echo $? after running that command, to see its return code -- that's what is important with it – Ale Oct 3 '14 at 9:55

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.