0 0 1 * * runs the job once a month, at 0:00 on the 1st. The third field pins the day of the month, month and weekday stay open, so the run happens twelve times a year regardless of which weekday the 1st falls on. The shortcut @monthly expands to exactly this line.
How do I run a job on the last day of the month?
Not with the day field alone: 0 0 31 * * skips every month that has 30 days, and February entirely. The standard trick is to run daily and let the script decide: 0 23 28-31 * * combined with a test like [ "$(date -d tomorrow +%d)" = "01" ] fires only on the actual last day, whatever its number.
What happens if I add a weekday to a monthly job?
It becomes far more frequent than intended. 0 0 1 * 1 does not mean “the 1st, if it is a Monday” — with both day fields restricted, cron links them with OR, so the job runs on the 1st and on every Monday, roughly five times a month. Friday the 13th simply cannot be expressed in cron; it needs a date check inside the script.
Is the 1st a good day for monthly billing runs?
It is the obvious choice and therefore the busiest: invoices, reports, quota resets and licence checks all cluster there, both on your machine and at every service you call. If the run depends on data that is only complete during the night, the 2nd at 4 a.m. is often the calmer and more reliable slot — cron has no retry, so a failed run waits a full month.
How to add the expression
- Put the day in the third field and leave the weekday field as a star, otherwise the OR rule doubles the schedule.
- Add 0 0 1 * * plus the command, or @monthly when the date is fixed for good.
- For the last day of a month, schedule 28-31 and check inside the script whether tomorrow is the 1st.
- Alert on failure: a monthly job that silently fails is only noticed in the next quarter.