4

I want to schedule my script for last Saturday of every month. I have come up with the below:

45 23 22-28 * *  test $(date +\%u) -eq 6 && echo "4th Saturday"  && sh  /folder/script.sh 

Is this correct or I need to change it? I can't test it right now as it will be invoked only on last saturday. Please advise.

I have the below for last sunday of every month but i can't understand much of it. The first part gives 24 which is sunday and after -eq gives 7 which i don't know what it means:

00 17  * * 0 [ $(cal -s | tail -2 | awk '{print $1}') -eq $(date | awk '{print $3}') ] && /folder/script.sh

Can I modify the above to get last saturday?

With Romeo's help I was help to come up with the below answer:

00 17 * * 6 [ $(cal -s | tail -2 | awk '{print $7}') -eq $(date | awk '{print $3}') ] && /folder/script.sh

5 Answers 5

12

Your logic will not work. Month can have last Saturday to be on 29 or 30 or 31. For this reason the best way to do the check is to run it every Saturday and check in script if this is in last 7 days in month:

45 23 * * 6  sh  /folder/script.sh 

and add in your script (here assuming the GNU implementation of date) something like:

if [ "$(date -d "+7 day" +%m)" -eq "$(date +%m)" ]
then echo "This is not one of last 7 days in month.";exit
fi
<rest of your script>

About your line in cron you should edit it to start like this:

00 17  * * 6

(6 means Saturday, 0 or 7 mean Sunday)

11
  • What if i extend the date range from 22-28 to 22-31? Because if have similar script for 3rd friday of every month with range 15-21 and -eq 5 and that works fine. Nov 7, 2019 at 7:01
  • 2
    @user3901666, in interval 22-31 you may have more than one Saturday. Check your calendar for November this year. And for last Saturday its different because you can have 5 Saturdays in month Nov 7, 2019 at 7:10
  • I have the cron for last sunday of each month (posted in the description), But i don't know how its works. Can i modify it to get the cron for saturday? Nov 7, 2019 at 7:19
  • The problem is I can't modify my script as it is a generic script which works for other schedules as well. Nov 7, 2019 at 7:19
  • @user3901666, you can always create a copy of this script and edit it :) Nov 7, 2019 at 7:20
1

If you happen to use the Dillon Crontab (which I believe it is better, includes more features, and supplies also anacron), then you have the option of:

If you specify both a day in the month and a day of week, it will be interpreted as the Nth such day in the month.

45 23 5 * 6  /path/script.sh

To request the last Monday, etc. in a month, ask for the "5th" one. This will always match the last Monday, etc., even if there are only four Mondays in the month

Hopefully you and others can use this answer for future consultation.


References:

0

What about this:

45 23 */25,*/26,*/27,*/28,*/29,*/30,*/31 * SAT

I have not tried this, but Crontab Guru says it's possible:

enter image description here

2
  • 1
    For a 30-day month, last Saturday could be the 24th (and if include 24, two Saturdays could match for 31-day months), so it doesn't match last saturday for every month.
    – thanasisp
    May 6, 2022 at 0:00
  • @thanasisp you are right. I was using similar script for Sundays and in September it would skip without 24th being used. With 24th being used then it would do it two times a month in some months. Well, if the task is not critical, its an ok solution - which is the case for me.
    – PaulM
    May 6, 2022 at 16:12
0

While the rest of the answers are framed in the way you asked the question (via cronjob).

It's important to note this is why systemd timers exist. They have more robust scheduling.

Instead of a cronjob, you create a systemd service and matching timer.

Use OnCalendar in timer

OnCalendar=Sat *-*~07/1 23:45:00

or more verbosely...

OnCalendar=Sat *-1,3,5,7,8,10,12-25..31 23:45:00
OnCalendar=Sat *-4,6,9,11-24..30 23:45:00
OnCalendar=Sat *-2-22..29 23:45:00

https://www.freedesktop.org/software/systemd/man/systemd.timer.html

https://www.freedesktop.org/software/systemd/man/systemd.time.html

https://wiki.archlinux.org/title/Systemd/Timers

https://documentation.suse.com/smart/linux/html/task-create-systemd-timers/index.html#id-1.5

-1
00 01 * * 6 [ $(date +\%d) -gt $(date \-d "-$(date +\%d) days month -7 days" +\%d) ] && /run/my/script

$(date +%d) is current day

$(date -d "-$(date +%d) days month -7 days" +%d) is "minus this months days (so previous month's last day) plus a month, minus 7 days."

So running on 14th Feb 2023 we get:

[ 14 -gt 21 ] && /run/my/script

So it wont run.

Get it to check on day 6 to run it every Saturday at the time you want.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .