svn commit: r346427 - in head/usr.sbin/cron: cron crontab
Kyle Evans
kevans at FreeBSD.org
Tue Sep 3 14:08:04 UTC 2019
Author: kevans
Date: Sat Apr 20 02:54:20 2019
New Revision: 346427
URL: https://svnweb.freebsd.org/changeset/base/346427
Log:
cron(8): schedule interval jobs that get loaded during execution
Jobs using the @<second> syntax currently only get executed if they exist
when cron is started. The simplest reproducer of this is:
echo '@20 root echo "Hello!"' >> /etc/cron.d/myjob
myjob will get loaded at the next second==0, but this echo job will not
run until cron restarts. These jobs are normally handled in
run_reboot_jobs(), which sets e->lastexit of INTERVAL jobs to the startup
time so they run 'n' seconds later.
Fix this by special-casing TargetTime > 0 in the database load. Preexisting
jobs will be handled at startup during run_reboot_jobs as normal, but if
we've reloaded a database during runtime we'll hit this case and set
e->lastexit to the current time when we process it. They will then run every
'n' seconds from that point, and a full restart of cron is no longer
required to make these jobs work.
Reported by: Juraj Lutter (otis_sk.freebsd.org)
Reviewed by: allanjude, bapt, bjk (earlier version), Juraj Lutter
MFC after: 3 days
Differential Revision: https://reviews.freebsd.org/D19924
Modified:
head/usr.sbin/cron/cron/database.c
head/usr.sbin/cron/crontab/crontab.5
Modified: head/usr.sbin/cron/cron/database.c
==============================================================================
--- head/usr.sbin/cron/cron/database.c Sat Apr 20 02:44:38 2019 (r346426)
+++ head/usr.sbin/cron/cron/database.c Sat Apr 20 02:54:20 2019 (r346427)
@@ -259,6 +259,8 @@ process_crontab(uname, fname, tabname, statbuf, new_db
struct passwd *pw = NULL;
int crontab_fd = OK - 1;
user *u;
+ entry *e;
+ time_t now;
if (strcmp(fname, SYS_NAME) && !(pw = getpwnam(uname))) {
/* file doesn't have a user in passwd file.
@@ -307,6 +309,21 @@ process_crontab(uname, fname, tabname, statbuf, new_db
u = load_user(crontab_fd, pw, fname);
if (u != NULL) {
u->mtime = statbuf->st_mtime;
+ /*
+ * TargetTime == 0 when we're initially populating the database,
+ * and TargetTime > 0 any time after that (i.e. we're reloading
+ * cron.d/ files because they've been created/modified). In the
+ * latter case, we should check for any interval jobs and run
+ * them 'n' seconds from the time the job was loaded/reloaded.
+ * Otherwise, they will not be run until cron is restarted.
+ */
+ if (TargetTime != 0) {
+ now = time(NULL);
+ for (e = u->crontab; e != NULL; e = e->next) {
+ if ((e->flags & INTERVAL) != 0)
+ e->lastexit = now;
+ }
+ }
link_user(new_db, u);
}
Modified: head/usr.sbin/cron/crontab/crontab.5
==============================================================================
--- head/usr.sbin/cron/crontab/crontab.5 Sat Apr 20 02:44:38 2019 (r346426)
+++ head/usr.sbin/cron/crontab/crontab.5 Sat Apr 20 02:54:20 2019 (r346427)
@@ -17,7 +17,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 15, 2019
+.Dd April 19, 2019
.Dt CRONTAB 5
.Os
.Sh NAME
@@ -245,12 +245,14 @@ string meaning
The
.Sq @
symbol followed by a numeric value has a special notion of running
-a job that much seconds after completion of previous invocation of
+a job that many seconds after completion of the previous invocation of
the job.
Unlike regular syntax, it guarantees not to overlap two or more
-invocations of the same job.
-The first run is scheduled specified amount of seconds after cron
-has started.
+invocations of the same job during normal cron execution.
+Note, however, that overlap may occur if the job is running when the file
+containing the job is modified and subsequently reloaded.
+The first run is scheduled for the specified number of seconds after cron
+is started or the crontab entry is reloaded.
.Sh EXAMPLE CRON FILE
.Bd -literal
More information about the svn-src-all
mailing list