Search code examples
linuxbashcron

How to define a cron expression that execute a script in the first monday of each month?


I have a script such as that:

* * * * * path/to/my/script.sh

I need to define the cron expression " * * * * * " to run once a month in the first Monday of each month.


Solution

  • The first monday of the month is the only monday that occurs during the first seven days of the month. Thus, to execute the job at 1:02 AM, use:

    2 1 1-7 * * test $(date +\%u) -eq 1 && path/to/my/script.sh
    

    The first two items, the numbers 1 and 2, set the minute and hour.

    The third item, 1-7, sets the allowed range for the day of the month.

    The fourth item, *, is the month and we allow all months to match.

    The fifth item, *, sets the day of the week. This field is OR'd with the day of the month field. Consequently, it is not useful to specify monday here. If we did, the cronjob would run on both the first seven days of the month and all mondays.

    Lastly, we have test $(date +\%u) -eq 1. This returns True only on mondays. Because of the && which follows it, your script will be executed only on the monday that occurs during the first seven days of the month.

    Note that, in crontab entries, % is treated as a newline unless it is escaped. Because we need a literal %, it is escaped with a backslash in the command above.

    For more on how this works see man 5 crontab.

    Alternative

    As twalberg points out, the same logic works the other way around. We can run the cronjob on every Monday and then test if that monday falls on one of the first seven days of the month:

    2 1 * * Mon  test $(date +\%e) -le 7 && path/to/my/script.sh