Cron job every three days - cron

Is it possible to run a cronjob every three days? Or maybe 10 times/month.

Run it every three days...
0 0 */3 * *
How about that?
If you want it to run on specific days of the month, like the 1st, 4th, 7th, etc... then you can just have a conditional in your script that checks for the current day of the month.
if (((date('j') - 1) % 3))
exit();
or, as #mario points out, you can use date('k') to get the day of the year instead of doing it based on the day of the month.

* * */3 * * that says, every minute of every hour on every three days.
0 0 */3 * * says at 00:00 (midnight) every three days.

I am not a cron specialist, but how about:
0 */72 * * *
It will run every 72 hours non-interrupted.
https://crontab.guru/#0_/72___

Because cron is "stateless", it cannot accurately express "frequencies", only "patterns" which it (apparently) continuously matches against the current time.
Rephrasing your question makes this more obvious: "is it possible to run a cronjob at 00:01am every night except skip nights when it had run within 2 nights?" When cron is comparing the current time to job request time patterns, there's no way cron can know if it ran your job in the past.
(it certainly is possible to write a stateful cron that records past jobs and thus includes patterns for matching against this state, but that's not the standard cron included in most operating systems. Such a system would get complicated by requiring the introduction of the concept of when such patterns "reset". For example, is the pattern reset when the time is changed (i.e. the crontab entry is revised)? Look to your favorite calendar app to see how complicated it can get to express Repeating patterns of scheduled events, and note that they don't have the reset problem because the starting calendar event has a natural "start" a/k/a "reset" date. Try rescheduling an every-other-week recurring calendar event to postpone by a week, over christmas for example. Usually you have to terminate that recurring event and restart a completely new one; this illustrates the limited expressivity of how even complicated calendar apps represent repeating patterns. And of course Calendars have a lot of state-- each individual event can be deleted or rescheduled independently [in most calendar apps]).
Further, you probably want to do your job every 3rd night if successful, but if the last one failed, to try again immediately, perhaps the next night (not wait 3 more days) or even sooner, like an hour later (but stop retrying upon morning's arrival). Clearly, cron couldn't possibly know if your job succeeded and the pattern can't also express an alternate more frequent "retry" schedule.
ANYWAY--
You can do what you want yourself. Write a script, tell cron to run it nightly at 00:01am. This script could check the timestamp of something* which records the "last run", and if it was >3 days ago**, perform the job and reset the "last run" timestamp.
(*that timestamped indicator is a bit of persisted state which you can manipulate and examine, but which cron cannot)
**be careful with time arithmetic if you're using human-readable clock time-- twice a year, some days have 23 or 25 hours in their day, and 02:00-02:59 occurs twice in one day or not at all. Use UTC to avoid this.

I don't think you have what you need with:
0 0 */3 * * ## <<< WARNING!!! CAUSES UNEVEN INTERVALS AT END OF MONTH!!
Unfortunately, the */3 is setting the interval on every n day of the month and not every n days. See: explanation here. At the end of the month there is recurring issue guaranteed.
1st at 2019-02-01 00:00:00
then at 2019-02-04 00:00:00 << 3 days, etc. OK
then at 2019-02-07 00:00:00
...
then at 2019-02-25 00:00:00
then at 2019-02-28 00:00:00
then at 2019-03-01 00:00:00 << 1 day WRONG
then at 2019-03-04 00:00:00
...
According to this article, you need to add some modulo math to the command being executed to get a TRUE "every N days". For example:
0 0 * * * bash -c '(( $(date +\%s) / 86400 \% 3 == 0 )) && runmyjob.sh'
In this example, the job will be checked daily at 12:00 AM, but will only execute when the number of days since 01-01-1970 modulo 3 is 0.
If you want it to be every 3 days from a specific date, use the following format:
0 0 * * * bash -c '(( $(date +\%s -d "2019-01-01") / 86400 \% 3 == 0 )) && runmyjob.sh'

0 0 1-30/3 * *
This would run every three days starting 1st. Here are the 20 scheduled runs -
2015-06-01 00:00:00
2015-06-04 00:00:00
2015-06-07 00:00:00
2015-06-10 00:00:00
2015-06-13 00:00:00
2015-06-16 00:00:00
2015-06-19 00:00:00
2015-06-22 00:00:00
2015-06-25 00:00:00
2015-06-28 00:00:00
2015-07-01 00:00:00
2015-07-04 00:00:00
2015-07-07 00:00:00
2015-07-10 00:00:00
2015-07-13 00:00:00
2015-07-16 00:00:00
2015-07-19 00:00:00
2015-07-22 00:00:00
2015-07-25 00:00:00
2015-07-28 00:00:00

How about:
00 00 * * * every 3 days && echo test
Where every is a script:
#!/bin/sh
case $2 in
days)
expr `date +%j` % $1 = 0 > /dev/null
;;
weeks)
expr `date +%V` % $1 = 0 > /dev/null
;;
months)
expr `date +%m` % $1 = 0 > /dev/null
;;
esac
So it runs every day.
Using */3 runs on the 3rd, 6th, ... 27th, 30th of the month, but is then wrong after a month has a 31st day. The every script is only wrong after the end of the year.

It would be simpler if you configured it to just run e.g. on monday and thursdays, which would give it a 3 and 4 day break.
Otherwise configure it to run daily, but make your php cron script exit early with:
if (! (date("z") % 3)) {
exit;
}

Since UTC days are exactly 86400 seconds (all of them, forget about leap seconds, they don't affect UTC days), dividing (integer division) the epoch time in seconds by 86400 gives us (full) elapsed days since epoch. With some more math we may arrive to this cron line:
12 21 * * * [ $(( ($(date +\%s)/86400+0) \% 3 )) = 0 ] && do_stuff
If today is 08/30/2021 at New_York the best time to execute the command is at 21:12 (or later) to ensure full days. At such time and date, the command will be executed. If there is the need to move the day, then change the 0 to an appropriate offset to get a 0-day on that day.
It is also possible to use any other cycle n (instead of 3).
The result is not affected by month, year or century. There will always be a cycle of n days
Note that cron requires that the % are escaped as \%.

If you want it to run on specific days of the month, like the 1st, 4th, 7th, etc... then you can just have a conditional in your script that checks for the current day of the month.
I thought all you needed for this was instead of */3 which means every three days, use 1/3 which means every three days starting on the 1st of the month. so 7/3 would mean every three days starting on the 7th of the month, etc.

0 0 * * * [ $(($((date +%-j- 1)) % 3)) == 0 ] && script
Get the day of the year from date, offset by 1 to start at 0, check if it is modulo three.

You should learn the basics of crontab.
Edit the cron by command crontab -e and then βŒƒ (CTRL) + X then Y and finally press ENTER (return) on mac to save the file. You can check the new crons have been installed of not by crontab -l
A crontab file has five fields for specifying mins, hours, the day of
the month, month, and the day of the week followed by the command to
be run at that interval.
* * * * * command to be executed
- - - - -
| | | | |
| | | | +----- day of week (0-6) (Sunday=0)
| | | +------- month (1-12)
| | +--------- day of month (1-31)
| +----------- hour (0-23)
+------------- min (0-59)
* in the value field above means all legal values as in braces for that column.
Here, I wrote a detailed post about it: Setup Cron in Unix

Related

Cron Scheduler - every quarter end third Sunday # 3:30 AM CST

Actually I am trying to schedule an application , which has to be run at
Cron expression to run application job for every end of quarter on 3rd Sunday at 3:30 AM CST
currently am using 0 */10 * ? * * - which runs for every ten minutes.
when I search on online ,this link https://crontab.guru/every-quarter
0 0 1 */3 * this would run for every quarter I guess.
But for my requirement , which I stated above, am not sure actually.
but , i referred some of the previous questions and some trial and error , I reached something like this 30 3 15-21 */3 SUN but am not sure. Please give your thoughts
OK .. for spring scheduler cron expression, below is my best bet
0 30 03 15-21 3,6,9,12 SUN
should work i think. tested partially. since, the above expression will run only on june.

Schedule cron job from 9:21AM till 02:30PM every 2 minutes

I want to schedule a cron job to run from 9:21 AM till 02:30 PM every 2 minutes from Monday to Friday. How can I do this ?. I know the following can do this from 9 AM till 4 PM, how can I modify this to achieve the above condition.
Thanks in advance.
*/2 09-16 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
This is actually the start of the right cron expression. To get what you're looking for, you'll actually have to combine several scheduled expressions, I believe
I highly recommend using the tool Crontab Guru to check your crontab expressions!
# β€œAt every 2nd minute from 21 through 60 past hour 9 on every day-of-week from Monday through Friday.”
21-60/2 9 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
# At every 2nd minute past every hour from 10 AM through 1:59 PM on every day-of-week from Monday through Friday.
*/2 10-13 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
# At every 2nd minute from 0 through 30 past hour 14 on every day-of-week from Monday through Friday.
0-30/2 14 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
Another note that could be helpful is checking the cron mail (I see you're logging, which is great!) but the system usually delivers cron mail detailing cron jobs as well.
Typically this is found in /var/spool/mail/{username}
There is no indication in the man page (man 5 crontab) that what you require is supported in any single line specification, as any ranges that you set will be applied for each time field (e.g. minute, hour) separately, so for example 21-30/2 9-14 ... would mean to run at 21,23,25,27,29 minutes past each of those hours.
You can of course achieve the desired effect using multiple lines:
21-59/2 9 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
1-59/2 10-13 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
1-30/2 14 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
In this case, it is helped a little by the fact that the interval is a factor of an hour, so at least the middle of these three lines will ensure regular intervals during the period 10:01 - 13:59. If you had an interval of, say, 7 minutes, then you would need even more lines to ensure a completely regular interval throughout.
Note also the following comment in the manual page:
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
specific 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.
So you could adopt this approach and just use for example:
1-59/2 9-14 * * 1-5 /temp/test_cron.sh >> /temp/test_cron.log
and perform some test in your shell script (or perhaps a wrapper script) such as:
hhmm=`date +%H%M`
if [ $hhmm -lt 0930 -o $hhmm -gt 1430 ]; then exit; fi
(here we are treating hhmm as a 4-digit decimal number)

how to run a cron job at a certain frequency starting from a specific date?

I tried using both npm packages "cron" and "node-schedule" to make this work, but i couldn't.
Let's say i want to start the cron job at 6.30PM, and starting from 6PM i want it to be executed every 2 hours.
First is that i couldn't make it work if it is not an exact hour , meaning if it is not (1PM,2PM,8PM.....)
So i supposed that it will run at 6PM sharp and not 6.30PM
I tried this pattern:
"0 18-23/2 * * *" which is supposed to work from 18 to 23, escaping two hours [18,20,22,00] but once it's past midnight it will stop til it's 18h again. i want it to keep executing every 2 hours (meaning it executes at 2AM and so on ...)
IS that possible with cron jobs ?
You could do a basic shell script to check if the current date and time are greater than or equal to the date and time you specify before executing the command.
Please note that the date and time are specified in UTC. This will cause the cron to run every 2 hours 30 minutes past the top of the hour but it wont actually activate until after 6PM December 3rd 2019 UTC. Also note that the date command may vary with different flavors of nix* / BSD / OSX.
30 */2 * * * if [ $(date --utc +%s) -ge $(date --utc --date "2019-12-03T18:00:00" +%s) ]; then (command) fi
I believe you are talking about using crontab to schedule jobs.
crontab is designed to let you set the frequency based on many things but it is not designed to become "enabled" a certain time.
so the following will run every two hours
0 0,2,4,6,8,10,12,14,16,18,20,22 * * * (command)
Lets say it is 1st of the month and you want it to run every two hours starting at 6 pm
I would do the following
0 18,20,22 1 * * (command)
0 0,2,4,6,8,10,12,14,16,18,20,22 2 * * (command)
This means that today (based on day of month it would run starting at 6 and tomorrow it will run every two hours. Then sometime tomorrow I would edit the file and remove the first line and change the '2' for the day of month to a '*' (to match the first line I showed you) -- now it will always run every two hours.
tldr; edit crontab to work for two days and then edit it after the go live to work for every day.

Cron Expression to be executed every n weeks

I am trying to write a Cron expression that triggers every n weeks.
I have thought about something like:
0 0 */21 * *
2013-09-01 00:00:00
2013-09-22 00:00:00
2013-10-01 00:00:00
2013-10-22 00:00:00
Per this Cron tester
But it triggers every 1st in addition to the 21st.
Ideas?
If you're using Quartz, then you may be able to accomplish that schedule with a SimpleTrigger instead:
Trigger trigger = newTrigger()
.withIdentity(triggerKey("myTrigger", "myGroup"))
.withSchedule(simpleSchedule()
.repeatHourlyForever(n * 7 * 24))
.startAt(...)
.build();
The '/' syntax specifies the increment during the period and not a repeat interval. Admittedly a subtle and confusing difference.
In this case there is only one available increment (21 days) during the 1 month period. The first number specifies the value to start with, in this case 0. Specifying '*' before the '/' is equivalent to specifying 0. So the job will only fire on the first day and at 21 days.
If you only want to fire the job once a month and not repeatedly then you could use the expression 0 0 21 * *.
If you want a job to trigger at a regular interval then you can use a Quartz SimpleTrigger with a repeatInterval specified.

Cron expression for only for wednesday every after 2 hours

java - Spring, i want to crate cron expression to run every after 2 hours only on Wednesday till day end
0 0 0/2 * * WED *
mean cron should trigger every wednessday only for these times 2am, 4am, 6am, 8am,10am, 12pm, 2pm,4pm, 6pm, 8pm, 10pm, 12pm
i don't have time long to wait and test can some one please confirm is it correct ?
Even though it is way to late i like to answer the question for other users.
Your CronExpression is invalid. You can check this here or here. The problem is: You cannot specify a day_of_month AND a day_of_week.
Cause you are setting a day_of_week you should skip day_of_month with a "?". Solution should be: 0 0 0/2 ? * WED *

Resources