]> granicus.if.org Git - cronie/commitdiff
Add support for RANDOM_DELAY of jobs.
authorTomas Mraz <tmraz@fedoraproject.org>
Tue, 11 Jun 2013 16:58:20 +0000 (18:58 +0200)
committerTomas Mraz <tmraz@fedoraproject.org>
Tue, 11 Jun 2013 16:58:20 +0000 (18:58 +0200)
man/crontab.5
src/cron.c
src/entry.c
src/env.c
src/globals.h
src/structs.h

index 740e39367f536cc5bce9c6a3df0b94c0ff49a580..bfc8414545dcf19085044650825187afd6b4a8fa 100644 (file)
@@ -143,6 +143,13 @@ specifications of the particular security context.  For more information,
 see
 .BR crontab (1)\ -s\ option.
 .PP
+The
+.I RANDOM_DELAY
+variable allows delaying job startups by random amount of minutes with
+upper limit specified by the variable. The random scaling factor is
+determined during the cron daemon startup so it remains constant for
+the whole run time of the daemon.
+.PP
 The format of a cron command is similar to the V7 standard, with a number
 of upward-compatible extensions.  Each line has five time-and-date fields
 followed by a
index 6fd0c314e04e87b8551e8562ba1cdc49217cbbc9..ec4ace7ca011f3c4e7d6d682e0efb0a24ca08a7b 100644 (file)
@@ -39,6 +39,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <sys/time.h>
 
 #ifdef WITH_INOTIFY
 # include <sys/inotify.h>
@@ -202,6 +203,9 @@ int main(int argc, char *argv[]) {
        char *cs;
        pid_t pid = getpid();
        long oldGMToff;
+       struct timeval tv;
+       struct timezone tz;
+       char buf[256];
 
        if ((ProgramName=strrchr(argv[0], '/')) == NULL) {
                ProgramName = argv[0];
@@ -298,6 +302,15 @@ int main(int argc, char *argv[]) {
        }
 
        pid = getpid();
+
+       /* obtain a random scaling factor for RANDOM_DELAY */
+       if (gettimeofday(&tv, &tz) != 0)
+               tv.tv_usec = 0;
+       srandom(pid + tv.tv_usec);
+       RandomScale = random() / (double)RAND_MAX;
+       snprintf(buf, sizeof(buf), "RANDOM_DELAY will be scaled with factor %d%% if used.", (int)(RandomScale*100));
+       log_it("CRON", pid, "INFO", buf, 0);
+
        acquire_daemonlock(0);
        database.head = NULL;
        database.tail = NULL;
@@ -508,8 +521,6 @@ static void run_reboot_jobs(cron_db * db) {
 
 static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long vGMToff) {
        char *orig_tz, *job_tz;
-       time_t virtualSecond = vtime * SECONDS_PER_MINUTE;
-       time_t virtualGMTSecond = virtualSecond - vGMToff;
        struct tm *tm;
        int minute, hour, dom, month, dow;
        user *u;
@@ -542,11 +553,7 @@ static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long v
        } while (0)
 
        orig_tz = getenv("TZ");
-       maketime(NULL, orig_tz);
 
-       Debug(DSCH, ("[%ld] tick(%d,%d,%d,%d,%d) %s %s\n",
-                       (long) getpid(), minute, hour, dom, month, dow,
-                       doWild ? " " : "No wildcard", doNonWild ? " " : "Wildcard only"));
                /* 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
@@ -561,6 +568,8 @@ static void find_jobs(int vtime, cron_db * db, int doWild, int doNonWild, long v
                                uname = e->pwd->pw_name;
                        /* check if user exists in time of job is being run f.e. ldap */
                        if (getpwnam(uname) != NULL) {
+                               time_t virtualSecond = (vtime - e->delay) * SECONDS_PER_MINUTE;
+                               time_t virtualGMTSecond = virtualSecond - vGMToff;
                                job_tz = env_get("CRON_TZ", e->envp);
                                maketime(job_tz, orig_tz);
                                /* here we test whether time is NOW */
index e9142f5a6dbffc8a1790457be49b6db3fd9da492..fa69524406bfabcb54687f3caf628ef63de640c9 100644 (file)
@@ -35,6 +35,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "bitstring.h"
 #include "funcs.h"
@@ -97,6 +98,7 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
        char cmd[MAX_COMMAND];
        char envstr[MAX_ENVSTR];
        char **tenvp;
+       char *p;
 
        Debug(DPARS, ("load_entry()...about to eat comments\n"));
 
@@ -297,6 +299,20 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
        }
        memset(e->pwd->pw_passwd, 0, strlen(e->pwd->pw_passwd));
 
+       p = env_get("RANDOM_DELAY", envp);
+       if (p) {
+               char *endptr;
+               long val;
+
+               errno = 0;    /* To distinguish success/failure after call */
+               val = strtol(p, &endptr, 10);
+               if (errno != 0 || val < 0 || val > 24*60) {
+                       log_it("CRON", getpid(), "ERROR", "bad value of RANDOM_DELAY", 0);
+               } else {
+                       e->delay = val * RandomScale;
+               }
+       }
+
        /* copy and fix up environment.  some variables are just defaults and
         * others are overrides.
         */
index 1ebea6299982d12cafdc41b44ec5afa847ff8787..3ad8bf79cb75b79f4ba19ab09d739970b626e28a 100644 (file)
--- a/src/env.c
+++ b/src/env.c
@@ -130,6 +130,7 @@ int env_set_from_environ(char ***envpp) {
                "LC_IDENTIFICATION",
                "LC_ALL",
                "LANGUAGE",
+               "RANDOM_DELAY",
                NULL
        };
        const char **name;
index 437097445924356453f4281ceeb517ef6a5c5e4f..e957c9adba6efe719af353a5c85d2040afa4a68b 100644 (file)
@@ -81,6 +81,7 @@ XTRN char       MailCmd[MAX_COMMAND];
 XTRN char       cron_default_mail_charset[MAX_ENVSTR];
 XTRN int        EnableClustering;
 XTRN int       ChangePath;
+XTRN double    RandomScale;
  
 #if DEBUGGING
 XTRN int       DebugFlags INIT(0);
index 200d20d95c36b415c0079df26ed5cfa27de6821a..272777aa674156fe8de0e052cd208cd895608daa 100644 (file)
@@ -41,6 +41,7 @@ typedef       struct _entry {
        bitstr_t        bit_decl(month,  MONTH_COUNT);
        bitstr_t        bit_decl(dow,    DOW_COUNT);
        int             flags;
+       int             delay;
 #define        MIN_STAR        0x01
 #define        HR_STAR         0x02
 #define        DOM_STAR        0x04