-2

I want to schedule some scripts in every alternate Saturday. I have tried few things like using days of the month but they don't seems to be the best ways to get the alternate days like
10 22 1-7,15-21,29-31 * 6

There should be some better solution to cron the things on alternate Saturdays.

Arun Kumar
  • 70
  • 8

1 Answers1

1

If you want to have special conditions, you generally need to implement the conditions yourself with a test. Below you see the general structure:

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
# |  |  |  |  |
# *  *  *  *  *   command to be executed
 10 22  *  *  6   testcmd && command

The command testcmd generally returns exit code 0 if the test is successful or 1 if it fails. If testcmd is successful, it executes command. A few examples that use similar tricks are in the following posts:

The easiest way to obtain what you are after is to select the Saturday to be falling on an odd or even week. The test command testcmd would then look like any of the following:

  • (( $(date "+\%d") \% 14 < 7 )) : group your month in groups of 14 days and select only the first seven of those days. This has issues that two consecutive weeks can be valid. Example, if the 30th of January is a Saturday, then both this Saturday and the next (6th of February) will be valid.
  • (( $(date "+\%V") \% 2 == 0 )) : group your year in groups of two weeks and select only the first of that week. This has the issue that years with 53 weeks can create two consecutive valid Saturdays on the end of December and the beginning of January. This is not frequent, but it can happen.

The most robust solution is that presented in * how to set cronjob for 2 days? where we change the problem to every 14 days. Based on my answer to that question, you can adapt it to form a little executable that would create you the perfect testcmd:

Replace in the above testcmd with /path/to/testcmd 14 20210731 where the latter is a script that reads;

#!/usr/bin/env bash
# get start time in seconds
start=$(date -d "${2:-@0}" '+%s')
# get current time in seconds
now=$(date '+%s')
# get the amount of days (86400 seconds per day)
days=$(( (now-start) /86400 ))
# set the modulo
modulo=$1
# do the test
(( days >= 0 )) && (( days % modulo == 0))
kvantour
  • 25,269
  • 4
  • 47
  • 72