Add per-second scheduling into the cron(8). Right now it's
only available via the new @every_second shortcut. ENOTIME to implement crontab(5) format extensions to allow more flexible scheduling. In order to address some concerns expressed by Terry Lambert while discussing the topic few years ago, about per-second cron possibly causing some bad effects on /etc/crontab by stat()ing it every second instead of every minute now (i.e. atime update), only check that database needs to be reloaded on every 60-th loop run. This should be close enough to the current behaviour. Add "@every_minute" shortcut while I am here. MFC after: 1 month
This commit is contained in:
parent
eecb11a14e
commit
4e207a1656
@ -98,6 +98,7 @@ main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
cron_db database;
|
||||
int runnum;
|
||||
|
||||
ProgramName = argv[0];
|
||||
|
||||
@ -149,21 +150,24 @@ main(argc, argv)
|
||||
load_database(&database);
|
||||
run_reboot_jobs(&database);
|
||||
cron_sync();
|
||||
runnum = 0;
|
||||
while (TRUE) {
|
||||
# if DEBUGGING
|
||||
/* if (!(DebugFlags & DTEST)) */
|
||||
# endif /*DEBUGGING*/
|
||||
cron_sleep(&database);
|
||||
|
||||
load_database(&database);
|
||||
if (runnum % 60 == 0)
|
||||
load_database(&database);
|
||||
|
||||
/* do this iteration
|
||||
*/
|
||||
cron_tick(&database);
|
||||
|
||||
/* sleep 1 minute
|
||||
/* sleep 1 second
|
||||
*/
|
||||
TargetTime += 60;
|
||||
TargetTime += 1;
|
||||
runnum += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,22 +198,23 @@ cron_tick(db)
|
||||
static time_t diff = 0, /* time difference in seconds from the last offset change */
|
||||
difflimit = 0; /* end point for the time zone correction */
|
||||
struct tm otztm; /* time in the old time zone */
|
||||
int otzminute, otzhour, otzdom, otzmonth, otzdow;
|
||||
int otzsecond, otzminute, otzhour, otzdom, otzmonth, otzdow;
|
||||
register struct tm *tm = localtime(&TargetTime);
|
||||
register int minute, hour, dom, month, dow;
|
||||
register int second, minute, hour, dom, month, dow;
|
||||
register user *u;
|
||||
register entry *e;
|
||||
|
||||
/* make 0-based values out of these so we can use them as indicies
|
||||
*/
|
||||
second = tm->tm_sec -FIRST_SECOND;
|
||||
minute = tm->tm_min -FIRST_MINUTE;
|
||||
hour = tm->tm_hour -FIRST_HOUR;
|
||||
dom = tm->tm_mday -FIRST_DOM;
|
||||
month = tm->tm_mon +1 /* 0..11 -> 1..12 */ -FIRST_MONTH;
|
||||
dow = tm->tm_wday -FIRST_DOW;
|
||||
|
||||
Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d)\n",
|
||||
getpid(), minute, hour, dom, month, dow))
|
||||
Debug(DSCH, ("[%d] tick(%d,%d,%d,%d,%d,%d)\n",
|
||||
getpid(), second, minute, hour, dom, month, dow))
|
||||
|
||||
if (dst_enabled && last_time != 0
|
||||
&& TargetTime > last_time /* exclude stepping back */
|
||||
@ -262,6 +267,7 @@ cron_tick(db)
|
||||
|
||||
/* make 0-based values out of these so we can use them as indicies
|
||||
*/
|
||||
otzsecond = otztm.tm_sec -FIRST_SECOND;
|
||||
otzminute = otztm.tm_min -FIRST_MINUTE;
|
||||
otzhour = otztm.tm_hour -FIRST_HOUR;
|
||||
otzdom = otztm.tm_mday -FIRST_DOM;
|
||||
@ -283,7 +289,8 @@ cron_tick(db)
|
||||
e->uid, e->gid, e->cmd))
|
||||
|
||||
if ( diff != 0 && (e->flags & (RUN_AT|NOT_UNTIL)) ) {
|
||||
if (bit_test(e->minute, otzminute)
|
||||
if (bit_test(e->second, otzsecond)
|
||||
&& bit_test(e->minute, otzminute)
|
||||
&& bit_test(e->hour, otzhour)
|
||||
&& bit_test(e->month, otzmonth)
|
||||
&& ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
|
||||
@ -302,7 +309,8 @@ cron_tick(db)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bit_test(e->minute, minute)
|
||||
if (bit_test(e->second, second)
|
||||
&& bit_test(e->minute, minute)
|
||||
&& bit_test(e->hour, hour)
|
||||
&& bit_test(e->month, month)
|
||||
&& ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
|
||||
|
@ -124,6 +124,10 @@
|
||||
LineNumber = ln; \
|
||||
}
|
||||
|
||||
#define FIRST_SECOND 0
|
||||
#define LAST_SECOND 59
|
||||
#define SECOND_COUNT (LAST_SECOND - FIRST_SECOND + 1)
|
||||
|
||||
#define FIRST_MINUTE 0
|
||||
#define LAST_MINUTE 59
|
||||
#define MINUTE_COUNT (LAST_MINUTE - FIRST_MINUTE + 1)
|
||||
@ -165,6 +169,7 @@ typedef struct _entry {
|
||||
#endif
|
||||
char **envp;
|
||||
char *cmd;
|
||||
bitstr_t bit_decl(second, SECOND_COUNT);
|
||||
bitstr_t bit_decl(minute, MINUTE_COUNT);
|
||||
bitstr_t bit_decl(hour, HOUR_COUNT);
|
||||
bitstr_t bit_decl(dom, DOM_COUNT);
|
||||
|
@ -232,6 +232,8 @@ string meaning
|
||||
@daily Run once a day, "0 0 * * *".
|
||||
@midnight (same as @daily)
|
||||
@hourly Run once an hour, "0 * * * *".
|
||||
@every_minute Run once a minute, "*/1 * * * *".
|
||||
@every_second Run once a second.
|
||||
.Ed
|
||||
.Sh EXAMPLE CRON FILE
|
||||
.Bd -literal
|
||||
|
@ -151,6 +151,7 @@ load_entry(file, error_func, pw, envp)
|
||||
e->flags |= WHEN_REBOOT;
|
||||
} else if (!strcmp("yearly", cmd) || !strcmp("annually", cmd)){
|
||||
Debug(DPARS, ("load_entry()...yearly shortcut\n"))
|
||||
bit_set(e->second, 0);
|
||||
bit_set(e->minute, 0);
|
||||
bit_set(e->hour, 0);
|
||||
bit_set(e->dom, 0);
|
||||
@ -159,6 +160,7 @@ load_entry(file, error_func, pw, envp)
|
||||
e->flags |= DOW_STAR;
|
||||
} else if (!strcmp("monthly", cmd)) {
|
||||
Debug(DPARS, ("load_entry()...monthly shortcut\n"))
|
||||
bit_set(e->second, 0);
|
||||
bit_set(e->minute, 0);
|
||||
bit_set(e->hour, 0);
|
||||
bit_set(e->dom, 0);
|
||||
@ -167,6 +169,7 @@ load_entry(file, error_func, pw, envp)
|
||||
e->flags |= DOW_STAR;
|
||||
} else if (!strcmp("weekly", cmd)) {
|
||||
Debug(DPARS, ("load_entry()...weekly shortcut\n"))
|
||||
bit_set(e->second, 0);
|
||||
bit_set(e->minute, 0);
|
||||
bit_set(e->hour, 0);
|
||||
bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
|
||||
@ -175,6 +178,7 @@ load_entry(file, error_func, pw, envp)
|
||||
bit_set(e->dow, 0);
|
||||
} else if (!strcmp("daily", cmd) || !strcmp("midnight", cmd)) {
|
||||
Debug(DPARS, ("load_entry()...daily shortcut\n"))
|
||||
bit_set(e->second, 0);
|
||||
bit_set(e->minute, 0);
|
||||
bit_set(e->hour, 0);
|
||||
bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
|
||||
@ -182,11 +186,28 @@ load_entry(file, error_func, pw, envp)
|
||||
bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
|
||||
} else if (!strcmp("hourly", cmd)) {
|
||||
Debug(DPARS, ("load_entry()...hourly shortcut\n"))
|
||||
bit_set(e->second, 0);
|
||||
bit_set(e->minute, 0);
|
||||
bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
|
||||
bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
|
||||
bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
|
||||
bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
|
||||
} else if (!strcmp("every_minute", cmd)) {
|
||||
Debug(DPARS, ("load_entry()...every_minute shortcut\n"))
|
||||
bit_set(e->second, 0);
|
||||
bit_nset(e->minute, 0, (LAST_MINUTE-FIRST_MINUTE+1));
|
||||
bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
|
||||
bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
|
||||
bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
|
||||
bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
|
||||
} else if (!strcmp("every_second", cmd)) {
|
||||
Debug(DPARS, ("load_entry()...every_second shortcut\n"))
|
||||
bit_nset(e->second, 0, (LAST_SECOND-FIRST_SECOND+1));
|
||||
bit_nset(e->minute, 0, (LAST_MINUTE-FIRST_MINUTE+1));
|
||||
bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
|
||||
bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
|
||||
bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
|
||||
bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
|
||||
} else {
|
||||
ecode = e_timespec;
|
||||
goto eof;
|
||||
|
Loading…
x
Reference in New Issue
Block a user