Answers
Lukasz Stelmach 2010-07-13T22:49:50
You can put something like this in the crontab file:\n\n00 09 * * 7 [ $(date +\\%d) -le 07 ] && /run/your/script\n\n\nThe date +%d gives you the number of the current day, and then you can check if the day is less than or equal to 7. If it is, run your command.\n\nIf you run this script only on Sundays, it should mean that it runs only on the first Sunday of the month.\n\nRemember that in the crontab file, the formatting options for the date command should be escaped.",
Mark Amery 2018-07-14T21:55:38
It's worth noting that what looks like the most obvious approach to this problem does not work.\n\nYou might think that you could just write a crontab entry that specifies the day-of-week as 0 (for Sunday) and the day-of-month as 1-7, like this...\n\n# This does NOT work.\n0 9 1-7 * 0 /path/to/your/script\n\n\n... but, due to an eccentricity of how Cron handles crontab lines with both a day-of-week and day-of-month specified, this won't work, and will in fact run on the 1st, 2nd, 3rd, 4th, 5th, 6th, and 7th of the month (regardless of what day of the week they are) and on every Sunday of the month.\n\nThis is why you see the recommendation of using a [ ... ] check with date to set up a rule like this - either specifying the day-of-week in the crontab and using [ and date to check that the day-of-month is <=7 before running the script, as shown in the accepted answer, or specifying the day-of-month range in the crontab and using [ and date to check the day-of-week before running, like this:\n\n# This DOES work.\n0 9 1-7 * * [ $(date +\\%u) = 7 ] && /path/to/your/script\n\n\nSome best practices to keep in mind if you'd like to ensure that your crontab line will work regardless of what OS you're using it on:\n\n\nUse =, not ==, for the comparison. It's more portable, since not all shells use an implementation of [ that supports the == operator.\nUse the %u specifier to date to get the day-of-week as a number, not the %a operator, because %a gives different results depending upon the locale date is being run in.\nJust use date, not /bin/date or /usr/bin/date, since the date utility has different locations on different systems.\n",
Dirk Eddelbuettel 2010-07-13T20:34:15
You need to combine two approaches:\n\na) Use cron to run a job every Sunday at 9:00am. \n\n 00 09 * * 7 /usr/local/bin/once_a_week\n\n\nb) At the beginning of once_a_week, compute the date and extract the day of the month via shell, Python, C/C++, ... and test that is within 1 to 7, inclusive. If so, execute the real script; if not, exit silently.",
Pēteris Caune 2022-09-23T10:48:04
There is a hacky way to do this with a classic (Vixie, Debian) cron:\n0 9 1-7 * */7\n\nThe day-of-week field starts with a star (*), and so cron considers it "unrestricted" and uses the AND logic between the day-of-month and the day-of-week fields.\n*/7 means "every 7 days starting from weekday 0 (Sunday)". Effectively, this means "every Sunday".\nHere's my article with more details: Schedule Cronjob for the First Monday of Every Month, the Funky Way\nNote – it's a hack. If you use this expression, make sure to document it to avoid confusion later.",