9

I'd like to know if L is one of the allowed special characters on Debian's cron implementation? I'm trying to set up a cron to run on the last day of every month.

From the cron entry on wikipedia:

'L' stands for "last". When used in the day-of-week field, it allows you to specify constructs such as "the last Friday" ("5L") of a given month. In the day-of-month field, it specifies the last day of the month.

Note: L is a non-standard character and exists only in some cron implementations (Quartz java scheduler)

If not, how would you go about setting a cron to run on the last day of every month? Would you recommend 3 different entries like this solution on stackoverflow?

4 Answers 4

6

Cron entries on Debian are described in the crontab man page (man 5 crontab). Debian uses Vixie's cron, and his man page says:

   The crontab syntax does not make it possible  to  define  all  possible
   periods  one could image off. For example, it is not straightforward to
   define the last weekday of a month. If a task needs to be run in a spe-
   cific  period of time that cannot be defined in the crontab syntaxs the
   best approach would be to have the program itself check  the  date  and
   time  information and continue execution only if the period matches the
   desired one.

   If the program itself cannot do the checks then a wrapper script  would
   be required. Useful tools that could be used for date analysis are ncal
   or calendar For example, to run a program the last  Saturday  of  every
   month you could use the following wrapper code:

   0 4 * * Sat   [ "$(date +%e)" = "`ncal | grep $(date +%a | sed  -e 's/.$//') 
     | sed -e 's/^.*\s\([0-9]\+\)\s*$/\1/'`" ] && echo "Last Saturday" &&
     program_to_run

So working along those lines:

   0 0 * * * perl -MTime::Local -e 
       'exit 1 if (((localtime(time()+60*60*24))[3]) < 2);' || program_to_run
4

I've never seen that L on a Linux cron implementation.

To run a job on the last day of the month, run it on a superset of the actual days and check the date of the next day. With GNU date, you can use date -d tomorrow to display the next day's date, so check if it's still in the same month. To avoid trouble in a few locations on a day when daylight savings time starts or end, specify a time of day that isn't the wee hours of the morning (12:00/noon in the examples). Remember that % is special in a crontab and needs to be protected by a backslash.

42 1 28-31 * * if [ "$(date -d 'today 12:00' +\%m)" != "$(date -d 'tomorrow 12:00' +\%m)" ]; then last_day_of_month_job; fi

You can apply the same technique for the last occurrence of a particular day of the week in the month. Run the job weekly and have it trigger only if the next occurrence would be in a different month.

42 1 * * 3 if [ "$(date -d 'today 12:00' +\%m)" != "$(date -d 'now + 7 days 12:00' +\%m)" ]; then last_wednesday_of_month_job; fi
2

Kind of awkward to check this experimentally I guess, since that would require changing your clock.

Debian uses the vixie cron implementation, which is referred to in the wikipedia article. The format for crontab expressions is explained in man 5 crontab, which is a little tricky, since man crontab is not the same thing (default section 1 is the command crontab, section 5 is for the format of "crontab" files).

It doesn't mention 'L'.

WRT the alternatives from S.O., the checked answer is the easiest to follow, and does not require an external script, etc. OTOH, it does have a leap year issue...

1
  • Yep, you could use a list on the 28,29th but then you'd get 2 runs on a leap year :(
    – Drav Sloan
    Commented Sep 2, 2013 at 22:57
0

My script has that feature, it isn't native cron but will do the trick.

http://xr09.github.io/cron-last-sunday/

Examples:

# every last sunday
30 6 * * 7 root run-if-today L && /root/myscript.sh

# every third tuesday
30 6 * * 2 root run-if-today 3 && /root/myscript.sh

You must log in to answer this question.

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