Is the following cron expression means every 45 minutes? - cron

Am willing to run a script every 45 minute (not the :45th minute of every hour)
e.g. 10:00, 10:45, 11:30, 12:15, and so on.
*/45 * * * *
Am not sure this is the correct expression.

I suspect (edit: I'm pretty sure by now) that it doesn't do what you want: fields are separate, and */45 for minutes is nothing more than 0,45. I would use the following three entries if */45 doesn't do the job:
0,45 0-23/3 * * *
30 1-23/3 * * *
15 2-23/3 * * *
If you take a look at entry.c file in vixie cron sources, you'll notice that each field of each entry is parsed by get_list and represented as bitmaps of allowed values for that field. That almost precludes any "smart" interpretation, as the distinction of */45 and 0,45 is lost at this stage... but there is a MIN_STAR flag, set at the presence of * in minutes (including */45). So we take a look at cron.c, a single place where MIN_STAR is examined, to learn it's unrelated to our problem. Now we know for sure that */45 means "every 45th minute of every hour": 0:00, 0:45, 1:00, 1:45 and so on.
There were two answers here confidently stating the opposite, quoting an unfortunate passage in the manual:
Steps are also permitted after an asterisk, so if you want to say
"every two hours", just use "*/2"
We are lucky to have a 24 hour day, containing even number of hours, making "every two hours from 0:00, each day" and "every two hours generally" indistinguishable. Too bad that the manual didn't go far enough to document non-trivial cases, making the impression that * */22 means every 22 hours. It does not. Star with a step is just a shorthand for a list of values in the field where it's used; it doesn't interact with other fields.

At the basic timing of cron, your system checks once per minute to see if there are any cronjobs to run. It will look at your crontab, and if it is time to run, poof, it runs! But every 45 minutes is an interval that will always hit at a 15 minute mark on the clock face. for example starting from zero the first is 0:45. Next will be 90 minutes from zero, or 1:30, the next will be 2:15... so easily you can see that the time for each instance you want to execute your script the minute hand will be on 12, 3, 6, or 9. If you execute your script every 15 minutes, and check the hour to see if it is the correct one, you can then execute your script. You will probably use either a table, or you might also use the modulo feature. Cheers!

Related

Is there a function for applying a date-diff to a cronexpression?

Suppose that I have a cron job which:
other admins might alter the cronexpression in the future, and
I want to notify users some fixed time (1 day, 2 hours, etc) in advance of every run of the job. It seems possible to construct a function (the particular language is not important to me) which inputs a valid cronexpression and a time difference ("+1d", "-12h", etc) and outputs a cronexpression which has been translated by some time delta (in the same way that many languages have a dateadd() for fixed, individual dates).
Examples:
- cronshift("0 2 12 * *", "-3h") => "0 23 11 * *" # 2am on the 12th
becomes 11pm on the 11th
- cronshift("0 1 * * 0,4", "-24h) => "0 1 * *
3,6" # 1am on Sun,Wed becomes 1am on Tues/Sat
- cronshift("0 1-3 12 *
*", "-2h") => ["0 23 11 * *", "0 0-1 12 * *"] # Extra credit: 1-3am on the 12th must be split across the 11th and 12th
Of course, there are a lot of complications (textual day-of-week names, '/' step values, etc) which I don't really need. Also, parsing the crontab to find/update the notification task is outside of the scope of this question. I also realize that another solution is to just calculate the date of the next cronexpression match, adjust that single date, and then make an at job to do the notification and create a new at job, but I'm intrigued by the complexity of time-shifting a cronexpression. Is there a module in any semi-popular scripting language that already does something like this?
Your are looking for a commercial grade scheduler with monitoring and logging with GUI and Web UI. Like this one.
I remember long ago there was a GUI utility for for cron and at. Named gnome-schedule hope it still exist.
You might also looking into higher-end task schedulers like Puppet and Jenkins
For high end scheduling with dynamic time calculations suggesting to use systemd timers.

Crontab, Meaning of */50 in Minutes Field

OK, I see a crontab line like:
*/50 * * * 1-6 command
Now, if my research is correct, something like */2 makes sense (minutes divided by 2, or every 2 minutes) and */5 makes sense (every 5 minutes).
In fact, the command happens to run at 50 minutes after the hour. Which makes sense as 60/50 is 0 remainder 50. But if that is the desired effect, why not just put 50 instead of */50?
Am I missing something, or did the original programmer just get too clever?
I'd like to just change it to 50, which I believe was the original intent, but I don't want to change anything without understanding the effects.
cron is stateless and does not remember when was the last time it executed a task.
From Wikipedia:
Note that frequencies in general cannot be expressed; only step values
which evenly divide their range express accurate frequencies (for
minutes and seconds, that's /2, /3, /4, /5, /6, /10, /12, /15, /20 and
/30 because 60 is evenly divisible by those numbers; for hours, that's
/2, /3, /4, /6, /8 and /12); all other possible "steps" and all other
fields yield inconsistent "short" periods at the end of the time-unit
before it "resets" to the next minute, second, or day; for example,
entering */5 for the day field sometimes executes after 1, 2, or 3
days, depending on the month and leap year; this is because cron is
stateless (it does not remember the time of the last execution nor
count the difference between it and now, required for accurate
frequency counting—instead, cron is a mere pattern-matcher).

Why crontab uses OR when both day of month and day of week specified?

It is a famous "problem" that when a crontab line contains both day of week and day of month cron uses OR for figuring out a day to fire the command.
E.g. if you write
* * 13 * 5 command
the command will execute on every Friday and every 13th day of month, not only on the Fridays that are 13th.
This contradicts the format for the other fields (when you write 30 2 * * * it will be executed only when both - hour AND minute - are exactly what you specified; same for all other fields except for DoW and DoM when they are both specified).
So my question is: is there a specific reason for this exception? I mean, there should be a reason, but I can't seem to find it. (And instead I see a lot of people in the internets who would like for these fields to be treated like any other - with the "AND strategy", precisely for stuff like "Friday 13th" or "2nd Thursday of May".)
Going back a step further from Vixie cron, the "wday OR mday" logic was present in System V cron, but not System III or anything earlier.
Before Paul Vixie wrote his cron replacement, BSD cron was like the SysIII-and-earlier cron. All 5 fields were ANDed. The post-4.4 BSDs adopted Vixie cron, making themselves more SysV-like.
So don't ask (blame) Vixie. He was just cloning SysV.
Why did SysV do that? I don't know but I'll try to provide some partial clues...
To try to understand what happened in SysV, it helps to look at the source (before - SysIII and after - SVr4) and also the documentation of the new behavior:
Note: the specification of days may be made by two fields (day of the month and day of the week). If both are specified as a list of elements, both are adhered to.
(Excerpt from SunOS 4.1.3 man page. It appears to be SysV-ish in this area. BSD cron never had this behavior before Paul Vixie wrote his replacement.)
"Both are adhered to" is a confusing substitute for a normal boolean expression using ANDs and ORs. It's still there in the OpenSolaris man page a couple of decades later:
The specification of days can be made by two fields (day of the month and day of the week). Both are adhered to if specified as a list of elements.
The SysV code is a complete rewrite. One of its features is that it sleeps for a long time when no jobs are due to run soon. (The older cron wakes up every minute and compares the current time to all job specifications.) A comment at the top of the calculation function (next_time) explains: NOTE: this routine is hard to understand.
It is indeed hard to understand. It is a "find next execution time for this crontab line" function, instead of a "decide whether the current time matches this crontab line" function, so it takes some effort to even figure out that the matching rule implicit in this function, when both mday and wday are non-*, is (month AND hour AND minute AND (mday OR wday)).
Based on that, combined with the way the documentation avoids explicitly telling us the boolean relationship between mday matching and wday matching, I'm going to guess that the person who wrote the new cron just wasn't thinking about it in those terms. They were thinking not about a combination of 5 booleans (corresponding directly to 5 fields in a struct tm), but about a set of 4 questions:
Is it the correct month?
Is it the correct day?
Is it the correct hour?
Is it the correct minute?
This leads naturally to the day comparisons being combined in their own way before ANDing everything else together. Maybe the SysV cron author just did what felt like the obvious thing at the time, without checking for compatibility with the old cron or pondering use cases like "first Saturday of every month".
Maybe this won't be a deep enough "why" to satisfy you - it certainly doesn't satisfy me - but a shallow answer is "because the standard says so".
Specifically, the POSIX standard dictates at http://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html that:
if either the month or day of month is specified as an element or list, and the day of week is also specified as an element or list, then any day matching either the month and day of month, or the day of week, shall be matched
(bolding mine).
I have no idea why this is what the standard requires. Interestingly, it seems like even Paul Vixie, who implemented Vixie Cron (the Cron implementation used on both Ubuntu and MacOS) doesn't know either; in cron.c there's this comment:
/* the dom/dow situation is odd. '* * 1,15 * Sun' will run on the
* first and fifteenth AND every Sunday; '* * * * Sun' will run *only*
* on Sundays; '* * 1,15 * *' will run *only* the 1st and 15th. this
* is why we keep 'e->dow_star' and 'e->dom_star'. yes, it's bizarre.
* like many bizarre things, it's the standard.
*/
So, by the sounds of it, even the implementer of the Cron you're probably using doesn't know the answer to your question in any more depth than the non-explanation I give in the first paragraph of this answer.
I work on a Unix server that uses many scripts in the crontab. It is very convenient for us to be able to indicate specific dates on scripts that should run on a single day of the week. In my case, I can't see why I would run a scheduled script on a day of the week ONLY if it is on a 13th, taking your example.

Perl Cron Scheduler: start at x time, execute every y minutes forever

I'm using perl cron, and I want to make a rule like this
run every xx min/hours starting at yy:yy time (until the end of time)
How would I put this into a cron string? perl:cron seems to use the same syntax as regular cron so a regular cron string should work
TIA!
The short answer is that you will either need to write this yourself or find a different third-party package, due to your requirements. There's two things you're asking for that cron doesn't do:
Run every X minutes.
Say you want to run every 40 minutes, and you write this */40 * * * *. This actually runs every 60 minutes at 1:40, 2:40, etc.
Start/Stop at time Y/Z.
There's simply no cron syntax for this. You could use a couple more cronjobs to add/remove the main cronjob at the specified times, but this smells a lot like self-modifying code. Given the complexity (read: unreliability), it's probably better to find a different system.
You can specify intervals with a slash. Here's every 5 minutes:
*/5 * * * *
This is every 2 hours:
0 */2 * * *
You cannot give a start/ end time in cron.

Specifying "all odd values" in crontab?

In crontab, I can use an asterisk to mean every value, or "*/2" to mean every even value.
Is there a way to specify every odd value? (Would something like "1+*/2" work?)
Depending on your version of cron, you should be able to do (for hours, say):
1-23/2
Going by the EXTENSIONS section in the crontab(5) manpage:
Ranges can include "steps", so "1-9/2" is the same as "1,3,5,7,9".
For a more portable solution, I suspect you just have to use the simple list:
1,3,5,7,9,11,13,15,17,19,21,23
But it might be easier to wrap your command in a shell script that will immediately exit if it's not called in an odd minute.
Every odd minute would be:
1-59/2 * * * *
Every even minute would be:
0-58/2 * * * *
I realize this is almost 10 years old, but I was having trouble getting 1-23/2 for an every two hour, odd hour job.
For all you users where, exact odd hour precision is not needed. I did the following which suited my teams needs.
59 */2 * * *
Execute the job every two hours, at the 59th Minute.
Try
1-23/2
From your question, I'm assuming Vixie Cron. I doubt this will work with any other cron.
As I read the manual "1-23/2" (for hours) would do the trick.
Works on Cronie
Even with 5 minutes interval e.g.
3-58/5 * * * * /home/test/bin/do_some_thing_every_five_minute

Resources