How do Cron Steps work?

I came across a situation where the cron job that I was thinking about worked every 55 minutes, actually works 55 minutes after the hour and at the top of the hour. This is actually not a cron job, but it is a PHP scheduling application that uses cron syntax.

When I ask this application to schedule work every 55 minutes, it creates a crontab line, as shown below.

*/55 * * * * 

This crontab line ends with no job running every 55 minutes. Instead, work takes place 55 minutes after the hour and at the top of the hour. I do not want it. I ran this though cron tester , and it checks that the unwanted behavior is the correct cron behavior.

This leads me to see what / means. When I looked at the cron manual , I found out that the slash is designated as “steps,” but the instruction itself is a little fuzzy, which means

Step values ​​can be used in conjunction with ranges. After the range with " <number> " indicates the passing of the value of the number through the range. For example, in the field of hours you can use " 0-23/2 " to indicate the execution of the command every hour (alternative in the V7 standard " 0,2,4,6,8,10,12,14,16,18,20,22" ). The steps are also allowed after the asterisk, so if you want to say "every two hours" just use " */2 ".

The manual’s description (“indicates missing values ​​over a range”) is a bit vague, and the “every two hours” example is a little misleading (which probably led to an error in the application)

So, two questions:

  • How does the unix cron program use step information (the number after the slash) to decide whether to skip the job? (modular division? If so, on what? With what conditions deciding the "true" run, and which solutions are not? Or is it something else?)

  • Is it possible to configure the unix cron job to run every "N" minutes?

+11
unix cron
source share
2 answers

Step values ​​can be used in conjunction with ranges. Following the range with " <number> " indicates passing the value of the number through the range. For example, “ 0-23/2 ” can be used in the hours field to indicate the execution of each other hour (alternative in the V7 standard is “ 0,2,4,6,8,10,12,14,16,18,20,22 "). Steps are also resolved after an asterisk, so if you want to say "every two hours," just use " */2 ".

The "range" referenced here is the range given before / , which is the subrange of the range of times for a particular field. The first field indicates minutes for an hour, therefore */... indicates a range from 0 to 59. The first field */55 indicates all minutes (within a range of 0-55) that are a multiple of 55 - that is, 0 and 55 minutes after every hour.

Similarly, 0-23/2 or */2 in the second (hourly) field indicates all hours (within the range 0-23) that are a multiple of 2.

If you specify the beginning of a range other than 0 , the number (say N ) after / indicates every minute Nth minute / hour / etc. at the bottom of the range. For example, 3-23/7 in the second field means every 7th hour starting at 03:00 (03:00, 10:00, 17:00).

This works best when the gap you want is evenly distributed over the next higher unit of time. For example, you can easily specify an event that should occur every 1, 2, 3, 4, 5, 6, 10, 12, 15, 20 or 30 minutes, or every 1, 2, 3, 4, 6 or 12 hours. ( Thanks to the Babylonians for choosing time units with so many nice divisors.)

Unfortunately, cron has no concept of "every 55 minutes" for a time exceeding an hour.

If you want to run the task every 55 minutes (for example, at 00:00, 00:55, 01:50, 02:45, etc.), you will have to do it indirectly. One approach is to schedule the script to run every 5 minutes; The script then checks the current time and executes its work only once every 11 times when it called.

Or you can use several lines in your crontab file to start the same work at 00:00, 00:55, 01:50, etc. - except that the day is not a multiple of 55 minutes. If you do not mind to have a longer or shorter interval once a day, week or month, you can write a program to create a large crontab with as many entries as you need, everyone works with the same command at the specified time.

+15
source share

There is another tool named at this point. It can be used instead of cron to achieve what the topic author wants. As far as I remember, it is preinstalled on OS X, but is not part of some Linux distributions, such as Debian (just apt install at ).

It starts the task at a specific time of the day, and this time can be calculated using a complex specification. In our case, you can use the following:

You can also specify the time, for example, now + calculate the units of time, where the units of time can be minutes, hours, days or weeks, and you can specify to complete the task today by adding the time suffix to today and starting the task tomorrow. adding time to tomorrow.

every2min.sh script runs every 2 minutes. This delays the following execution each time the instance is running:

 #!/bin/sh at -f ./every2min.sh now + 2 minutes echo "$(date +'%F %T') running..." >> /tmp/every2min.log 

What are the findings

 2019-06-27 14:14:23 running... 2019-06-27 14:16:00 running... 2019-06-27 14:18:00 running... 

Since at does not know about the unit of "seconds", the execution time will be rounded to the full minute after the first start. But for this task (with an interval of 55 minutes) this should not be a big problem.

There may also be security concerns.

For the at and batch commands, the commands are read from standard input or the file specified using the -f option and are executed. The working directory, environment (except for the variables BASH_VERSINFO, DISPLAY, EUID, GROUPS, SHELLOPTS, TERM, UID and _) and umask are saved from the time of the call.

This is the easiest way to schedule something to run every X minutes I've seen so far.

0
source share

All Articles