.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
.\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $OpenBSD: crontab.5,v 1.41 2020/04/18 17:11:40 jmc Exp $
+.\" $OpenBSD: crontab.5,v 1.42 2023/05/06 23:06:27 millert Exp $
.\"
-.Dd $Mdocdate: April 18 2020 $
+.Dd $Mdocdate: May 6 2023 $
.Dt CRONTAB 5
.Os
.Sh NAME
.Ql ~
are omitted, the appropriate limit (low or high) for the field will be used.
.Pp
-Step values can be used in conjunction with ranges (but not random ranges
-which represent a single number).
+Step values can be used in conjunction with ranges.
Following a range with
.No / Ns Ar number
specifies skips of
.Dq every two hours ,
just use
.Dq */2 .
+A step value after a random range will execute the command at a random
+offset less than the step size.
+For example, to avoid a thundering herd at the top and bottom of the hour,
+.Dq 0~59/30
+.Po
+or simply
+.Dq ~/30
+.Pc
+can be used in the
+.Ar minute
+field to specify that command execution happen twice an hour at
+consistent intervals.
.Pp
An asterisk
.Pq Ql *
-/* $OpenBSD: entry.c,v 1.53 2022/05/21 01:21:29 deraadt Exp $ */
+/* $OpenBSD: entry.c,v 1.54 2023/05/06 23:06:27 millert Exp $ */
/*
* Copyright 1988,1990,1993,1994 by Paul Vixie
/* range = number | number* "~" number* | number "-" number ["/" number]
*/
- int i, num1, num2, num3;
+ int i, num1, num2, num3, rndstep;
num1 = low;
num2 = high;
+ rndstep = 0;
if (ch == '*') {
/* '*' means [low, high] but can still be modified by /step
/* get the (optional) number following the tilde
*/
- ch = get_number(&num2, low, names, ch, file, ", \t\n");
+ ch = get_number(&num2, low, names, ch, file, "/, \t\n");
if (ch == EOF)
ch = get_char(file);
if (ch == EOF || num1 > num2) {
return (EOF);
}
+ if (ch == '/') {
+ /* randomize the step value instead of num1
+ */
+ rndstep = 1;
+ break;
+ }
+
/* get a random number in the interval [num1, num2]
*/
num3 = num1;
ch = get_number(&num3, 0, NULL, ch, file, ", \t\n");
if (ch == EOF || num3 == 0)
return (EOF);
+ if (rndstep) {
+ /*
+ * use a random offset smaller than the step size
+ * and the difference between high and low values.
+ */
+ num1 += arc4random_uniform(MINIMUM(num3, num2 - num1));
+ }
} else {
/* no step. default==1.
*/
-/* $OpenBSD: macros.h,v 1.15 2015/11/12 21:12:05 millert Exp $ */
+/* $OpenBSD: macros.h,v 1.16 2023/05/06 23:06:27 millert Exp $ */
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
#define MAX_TEMPSTR 100 /* obvious */
#define MAX_UNAME (_PW_NAME_LEN+1) /* max length of username, should be overkill */
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+
#define Skip_Blanks(c, f) \
while (c == '\t' || c == ' ') \
c = get_char(f);