From: Wayne on
On 5/19/2010 6:13 PM, Andrew L. wrote:
> ...
>
> You could say "run on Sunday of every month but only where Sunday is the
> 20-25th day of the month"
>
> 0 8 20-25 * 0 /path/to/script.sh

that says to run on every Sunday and also every day from the 20th thru
the 25th. when you specify both day of month and day of week, the
result is a Boolean OR, not AND. I always felt that was bizarre but
all Unixes have always worked this way.
>
> I think the best method would be to say "run on every Sunday of the month:"
>
> 0 8 * * 0 /path/to/script.sh
>
> Then within your script, before it executes, have verbage there to check
> if it in fact is the last Sunday of the month, it not, exit script.

I think this is the best way. Here's some code you can use in script.sh:

##########Start of file##########
# script.sh - run on the last Sunday of each month:
.. date_utils.sh

if ! last_week_of_month; then return; fi
# ...rest of script goes here...
##########End of file##########

And here's the file date_utils.sh:

##########Start of file##########
is_leap_year() {
year=$(date +%Y)
[ "$((year % 4))" -ne 0 ] && return 1; # not a leap year
[ "$((year % 400))" -eq 0 ] && return 0; # a leap year
[ "$((year % 100))" -eq 0 ] && return 1; # not a leap year
}

last_week_of_month() {
month=$(date +%m)
today=$(date +%d)

case "$month" in
1|3|5|7|8|10|12) last=31 ;;
2) is_leap_year && last=29 || last=28 ;;
*) last=30 ;;
esac

test $today -gt $((last - 7));
return $?
}
##########End of file##########

Note this avoids using cal, whose output format isn't specified by POSIX.
Feel free to improve on this code.

--
Wayne