Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bug#460070: cron: Using day-of-month and day-of-week together doesn't work as expected

26 views
Skip to first unread message

Chris Butler

unread,
Jan 10, 2008, 6:40:09 AM1/10/08
to
Package: cron
Version: 3.0pl1-100
Severity: normal

Using the following crontab:

21 11 5-15 * Thu echo test1
21 11 5-15 * Fri echo test2

Yields the following result:

Jan 10 11:21:01 pie /USR/SBIN/CRON[14172]: (chrisb) CMD (echo test2)
Jan 10 11:21:01 pie /USR/SBIN/CRON[14175]: (chrisb) CMD (echo test1)

In other words, the day-of-week value seems to be ignored. If I replace
day-of-month with '*', I get the expected behaviour.

-- System Information:
Debian Release: 4.0
APT prefers stable
APT policy: (990, 'stable'), (700, 'testing')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/dash
Kernel: Linux 2.6.18-4-k7
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_GB.UTF-8)

Versions of packages cron depends on:
ii adduser 3.102 Add and remove users and groups
ii debianutils 2.17 Miscellaneous utilities specific t
ii libc6 2.3.6.ds1-13etch4 GNU C Library: Shared libraries
ii libpam0g 0.79-5 Pluggable Authentication Modules l
ii libselinux1 1.32-3 SELinux shared libraries
ii lsb-base 3.1-23.2etch1 Linux Standard Base 3.1 init scrip

Versions of packages cron recommends:
ii postfix [mail-transport-agent 2.3.8-2+b1 A high-performance mail transport

-- no debconf information

--
To UNSUBSCRIBE, email to debian-bugs-...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listm...@lists.debian.org

Ángel

unread,
Jan 2, 2023, 10:20:04 PM1/2/23
to
The above patch by Mr. Feliz changed the semantics of crontab by making
cron AND the dom and dow fields instead of the default OR-when-not-
star. This would be more consistent overall, but that ship has sailed
decades ago.

Interestingly, the cron on early versions of UNIX [1] doesn't seem to
have that behavior but the "normal" one (it might have been a bug in
the scheduling). Although some time later it got clearly spelled on
SUSv2 [2] (probably on v1 as well), and Vixie even defines it as a
"bizarre" but "it's the standard".

With the odd behavior set in stone, using day-of-month and day-of-week
together (which would be useful, as already shown on this bug) requires
using a syntax which doesn't conflict with the previous one (that SHALL
keep working as-is).

The attached patch allows adding an optional '&&' token (surrounded by
whitespace) before the day of week field to mark that the day of week
of this line must match *in addition* to the day of month field. Since
it's a per-entry marker, lines ANDing the fields and ORing the fields
can be freely mixed in the same file. As a counterpart to &&, a '||'
token is also recognised at the same place although it's a no-op merely
for presentation purposes, since it "selects" the default behavior
(marking entries with dom and dow can be useful as an explicit reminder
of the dow gotcha).

The original crontab would look like this
21 11 5-15 * && Thu echo test1
21 11 5-15 * && Fri echo test2

which is much nicer than the date tests embedded in the command


The patch is also available at
https://salsa.debian.org/Angel-guest/cron/-/tree/bug460070

Regards


[1]
https://minnie.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/cmd/cron.c
https://minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/man/man8/cron.8
https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/cron.c
https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/man/man8/cron.8
https://minnie.tuhs.org/cgi-bin/utree.pl?file=2.9BSD/usr/src/cmd/cron.c

[2] - https://pubs.opengroup.org/onlinepubs/7908799/xcu/crontab.html
Allow-using-dom-and-dow-together.patch

Georges Khaznadar

unread,
Aug 28, 2023, 1:00:05 PM8/28/23
to
Hello Ángel,
thank you for reviving this old bug report, with new ideas.

I adopted the cron package a few months ago, and I would like to reduce
the number of open bugs, in order to gain visibility for future bug
reports to come.

The bug report about the oddities of "day-of-month and day-of-week
together" has been raised fifteen years ago, and no consensus has been
achieved about it. Christian Kastner, the previous maintainer, tagged
this bug wontfix, with severity wishlist, thirty years ago.

I believe that sysadmins should adopt sane methods, like the method
documented in the manpage crontab.5: using the command `date` which is
rather powerful to tackle such particular expressions combining
day-of-month and day-of-week, even in subtle combinations.

Here is an excerpt of the manpage which can be considered:

#Execute early the next morning following the first
#Thursday of each month
57 2 * * 5 case $(date +d) in 0[2-8]) echo "After 1st Thursday"; esac

If you do not mind, I shall close this bug report in a few weeks. Please
feel free to repoen it when necessary.

Best regards, Georges.

Ángel a écrit :
> Description: Allow using day-of-month and day-of-week together
> by prepending a `&&' token (surrounded by whitespace) to the
> dow field in order to take into account both dom and dow, from
> the standardised default of matching either of them.
> .
> For symmetry, an `||' is also allowed at the same place, useful
> mainly to serve as a reminder of this unintuitive behavior.
> Bug-Debian: https://bugs.debian.org/460070
> Last-Update: 2023-01-02
> Index: cron/cron.c
> ===================================================================
> --- cron.orig/cron.c
> +++ cron/cron.c
> @@ -336,6 +336,8 @@ find_jobs(vtime, db, doWild, doNonWild)
> * 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.
> + * We add as an extension the syntax '* * 1,15 * && Sun' to run only
> + * on the 1st and 15th that are Sundays.
> */
> for (u = db->head; u != NULL; u = u->next) {
> for (e = u->crontab; e != NULL; e = e->next) {
> @@ -345,7 +347,7 @@ find_jobs(vtime, db, doWild, doNonWild)
> if (bit_test(e->minute, minute) &&
> bit_test(e->hour, hour) &&
> bit_test(e->month, month) &&
> - ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
> + ( ((e->flags & DOM_STAR) || (e->flags & (DOW_STAR | DOW_AND)))
> ? (bit_test(e->dow,dow) && bit_test(e->dom,dom))
> : (bit_test(e->dow,dow) || bit_test(e->dom,dom)))) {
> if ((doNonWild && !(e->flags & (MIN_STAR|HR_STAR)))
> Index: cron/cron.h
> ===================================================================
> --- cron.orig/cron.h
> +++ cron/cron.h
> @@ -190,6 +190,7 @@ typedef struct _entry {
> #define WHEN_REBOOT 0x04
> #define MIN_STAR 0x08
> #define HR_STAR 0x10
> +#define DOW_AND 0x20
> } entry;
>
> /* the crontab database will be a list of the
> Index: cron/crontab.5
> ===================================================================
> --- cron.orig/crontab.5
> +++ cron/crontab.5
> @@ -216,8 +216,13 @@ field matches the current time. For exa
> .br
> ``30 4 1,15 * 5''
> would cause a command to be run at 4:30 am on the 1st and 15th of each
> -month, plus every Friday. One can, however, achieve the desired result
> -by adding a test to the command (see the last example in EXAMPLE CRON FILE
> +month, plus every Friday. To allow running it the 1st and 15th of each
> +month
> +.I only when they are Friday
> +this cron allows prepending a ``&&'' token before the day of week to get
> +that behavior (for symmetry, it is also possible to prepend a ``||'',
> +with the above default behavior). Alternatively, one can add a test for
> +the date into the command (see the last example in EXAMPLE CRON FILE
> below).
> .PP
> Instead of the first five fields, one of eight special strings may appear:
> @@ -273,7 +278,8 @@ MAILTO=paul
> 0 */4 1 * mon echo "run every 4th hour on the 1st and on every Monday"
> 0 0 */2 * sun echo "run at midn on every Sunday that's an uneven date"
> # Run on every second Saturday of the month
> -0 4 8\-14 * * test $(date +\e%u) \-eq 6 && echo "2nd Saturday"
> +0 4 8\-14 * && sat echo "2nd Saturday"
> +0 4 8\-14 * * test $(date +\e%u) \-eq 6 && echo "2nd Saturday"
> .fi
>
> .PP
> Index: cron/entry.c
> ===================================================================
> --- cron.orig/entry.c
> +++ cron/entry.c
> @@ -85,6 +85,8 @@ load_entry(file, error_func, pw, envp)
> * minutes hours doms months dows cmd\n
> * system crontab (/etc/crontab):
> * minutes hours doms months dows USERNAME cmd\n
> + *
> + * optionally: '&&' or '||' (surrounded by whitespace) before dows
> */
>
> ecode_e ecode = e_none;
> @@ -218,6 +220,46 @@ load_entry(file, error_func, pw, envp)
>
> if (ch == '*')
> e->flags |= DOW_STAR;
> +
> + if (ch == '&') {
> + e->flags |= DOW_AND;
> + ch = get_char(file);
> + if (ch != '&') {
> + ecode = e_dow;
> + goto eof;
> + }
> +
> + ch = get_char(file);
> + if (ch != '\t' && ch != ' ') {
> + ecode = e_dow;
> + goto eof;
> + }
> + Skip_Blanks(ch, file);
> +
> + if (ch == EOF) {
> + ecode = e_dow;
> + goto eof;
> + }
> + } else if (ch == '|') {
> + ch = get_char(file);
> + if (ch != '|') {
> + ecode = e_dow;
> + goto eof;
> + }
> +
> + ch = get_char(file);
> + if (ch != '\t' && ch != ' ') {
> + ecode = e_dow;
> + goto eof;
> + }
> + Skip_Blanks(ch, file);
> +
> + if (ch == EOF) {
> + ecode = e_dow;
> + goto eof;
> + }
> + }
> +
> ch = get_list(e->dow, FIRST_DOW, LAST_DOW,
> DowNames, ch, file);
> if (ch == EOF) {


--
Georges KHAZNADAR et Jocelyne FOURNIER
22 rue des mouettes, 59240 Dunkerque France.
Téléphone +33 (0)3 28 29 17 70

signature.asc
0 new messages