Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Jul 2001 21:17:28 -0400
From:      dchapes@ddm.crosswinds.net (Dave Chapeskie)
To:        Matthew Jacob <mjacob@feral.com>
Cc:        hackers@FreeBSD.ORG
Subject:   Re: perhaps one of phk's "intern" projects?
Message-ID:  <20010726211728.B89345@ddm.crosswinds.net>
In-Reply-To: <20010726154548.I18705-100000@wonky.feral.com>; from mjacob@feral.com on Thu, Jul 26, 2001 at 03:45:58PM -0700
References:  <Pine.BSF.4.21.0107261650250.97678-100000@xena.gsicomp.on.ca> <20010726154548.I18705-100000@wonky.feral.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--1Ow488MNN9B9o/ov
Content-Type: multipart/mixed; boundary="y2zxS2PfCDLh6JVG"
Content-Disposition: inline


--y2zxS2PfCDLh6JVG
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Thu, 26 Jul 2001, Matthew Jacob wrote:
> It'd be nice if one could pass a time specification to at in the form
> of "next reboot".
>
> -matt

On Thu, 26 Jul 2001, Matthew Emmerton replied:
> Why not just write a script for the command and stick it in
> /usr/local/etc/rc.d?
>
> -- Matt Emmerton

On Thu, Jul 26, 2001 at 03:45:58PM -0700, Matthew Jacob replied:
> Because I thought this might be of general utility.


Okay, try the attached patch.  If this is really something that might be
generally usefully I can submit the patch as a PR.

It allows "at reboot" and "at reboot + 1 hour", etc.

It does it by sticking the job in the queue with the filename prefixed
with "_" (yeah, a bit ugly, it was the first thing that came to me) and
with the runtime based on the epoch instead of the current time.

Adding:
	@reboot		root /usr/libexec/atrun -b
to /etc/crontab causes atrun(8) to rename all of these jobs adding the
current time to the jobs runtime.


% echo "echo test" | at reboot
Job 19 will be executed using /bin/sh

% echo "echo test" | at reboot + 90 minutes
Job 20 will be executed using /bin/sh

% atq
Date                    Owner   Queue   Job#
REBOOT                  dchapes c       19
REBOOT+01:30:00         dchapes c       20

$ date; /usr/libexec/atrun -b

% atq -v
Date                    Owner   Queue   Job#
22:34:00 07/26/01       dchapes c       20
21:04:00 07/26/01       dchapes c(done) 19

--=20
Dave Chapeskie <dchapes@ddm.crosswinds.net>
OpenPGP Key KeyId: 3D2B6B34

--y2zxS2PfCDLh6JVG
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="at.patch"

Index: usr.bin/at/at.h
===================================================================
RCS file: /cvs/FreeBSD/src/usr.bin/at/at.h,v
retrieving revision 1.5
diff -u -r1.5 at.h
--- usr.bin/at/at.h	2001/07/24 14:15:51	1.5
+++ usr.bin/at/at.h	2001/07/26 22:38:53
@@ -29,3 +29,4 @@
 extern char *namep;
 extern char atfile[];
 extern char atverify;
+extern int reboot_time;
Index: usr.bin/at/parsetime.c
===================================================================
RCS file: /cvs/FreeBSD/src/usr.bin/at/parsetime.c,v
retrieving revision 1.21
diff -u -r1.21 parsetime.c
--- usr.bin/at/parsetime.c	2001/07/24 14:15:51	1.21
+++ usr.bin/at/parsetime.c	2001/07/26 23:28:28
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *  at [NOW] PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS
+ *  at [NOW|REBOOT] PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS
  *     /NUMBER [DOT NUMBER] [AM|PM]\ /[MONTH NUMBER [NUMBER]]             \
  *     |NOON                       | |[TOMORROW]                          |
  *     |MIDNIGHT                   | |[DAY OF WEEK]                       |
@@ -63,7 +63,7 @@
 
 enum {	/* symbols */
     MIDNIGHT, NOON, TEATIME,
-    PM, AM, TOMORROW, TODAY, NOW,
+    PM, AM, TOMORROW, TODAY, NOW, REBOOT,
     MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS,
     NUMBER, PLUS, DOT, SLASH, ID, JUNK,
     JAN, FEB, MAR, APR, MAY, JUN,
@@ -86,6 +86,7 @@
     { "tomorrow", TOMORROW,0 },	/* execute 24 hours from time */
     { "today", TODAY, 0 },	/* execute today - don't advance time */
     { "now", NOW,0 },		/* opt prefix for PLUS */
+    { "reboot", REBOOT, 0 },	/* execute on next reboot */
 
     { "minute", MINUTES,0 },	/* minutes multiplier */
     { "minutes", MINUTES,1 },	/* (pluralized) */
@@ -280,7 +281,7 @@
 /*
  * plus() parses a now + time
  *
- *  at [NOW] PLUS NUMBER [MINUTES|HOURS|DAYS|WEEKS|MONTHS|YEARS]
+ *  at [NOW|REBOOT] PLUS NUMBER [MINUTES|HOURS|DAYS|WEEKS|MONTHS|YEARS]
  *
  */
 
@@ -563,6 +564,7 @@
  */
     time_t nowtimer, runtimer;
     struct tm nowtime, runtime;
+    int t;
     int hr = 0;
     /* this MUST be initialized to zero for midnight/noon/teatime */
 
@@ -579,6 +581,22 @@
     init_scanner(argc-optind, argv+optind);
 
     switch (token()) {
+    case REBOOT:
+	    reboot_time = 1;
+	    /* Reset "now" to be the epoch */
+	    nowtimer = 0;
+	    nowtime = *localtime(&nowtimer);
+	    runtime = nowtime;
+	    runtime.tm_sec = 0;
+	    runtime.tm_isdst = 0;
+
+	    t = token();
+	    if (t == PLUS)
+		plus(&runtime);
+	    else if (t != EOF)
+		plonk(sc_tokid);
+	    break;
+
     case NOW:	/* now is optional prefix for PLUS tree */
 	    expect(PLUS);
     case PLUS:
Index: usr.bin/at/at.c
===================================================================
RCS file: /cvs/FreeBSD/src/usr.bin/at/at.c,v
retrieving revision 1.19
diff -u -r1.19 at.c
--- usr.bin/at/at.c	2001/07/24 14:15:51	1.19
+++ usr.bin/at/at.c	2001/07/26 23:53:47
@@ -108,7 +108,8 @@
 
 extern char **environ;
 int fcreated;
-char atfile[] = ATJOB_DIR "12345678901234";
+char atfile[] = ATJOB_DIR "_Q1234512345678";
+int reboot_time = 0;		/* if 'reboot' was specified */
 
 char *atinput = (char*)0;	/* where to get input from */
 char atqueue = 0;		/* which queue to examine for jobs (atq) */
@@ -263,6 +264,8 @@
     if ((jobno = nextjob()) == EOF)
 	perr("cannot generate job number");
 
+    if (reboot_time)
+	    *ppos++ = '_';
     sprintf(ppos, "%c%5lx%8lx", queue, 
 	    jobno, (unsigned long) (runtimer/60));
 
@@ -455,7 +458,9 @@
     long jobno;
     time_t runtimer;
     char timestr[TIMESIZE];
+    char tmp[TIMESIZE];
     int first=1;
+    int after_boot;
     
 #ifdef __FreeBSD__
     (void) setlocale(LC_TIME, "");
@@ -483,22 +488,48 @@
 	    || !(S_IXUSR & buf.st_mode || atverify))
 	    continue;
 
-	if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
-	    continue;
+	if (dirent->d_name[0] == '_') {
+	    if(sscanf(dirent->d_name, "_%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
+		continue;
+	    after_boot = 1;
+	} else {
+	    if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
+		continue;
+	    after_boot = 0;
+	}
 
 	if (atqueue && (queue != atqueue))
 	    continue;
 
 	runtimer = 60*(time_t) ctm;
-	runtime = *localtime(&runtimer);
-	strftime(timestr, TIMESIZE, "%X %x", &runtime);
+	if (after_boot) {
+	    strlcpy(timestr,"REBOOT",sizeof timestr);
+	    if (ctm != 0) {
+		runtime = *gmtime(&runtimer);
+		if (runtime.tm_year != 70) {	/* 1970, the epoch */
+		    snprintf(tmp,sizeof tmp,"+%dyr",runtime.tm_year-70);
+		    strlcat(timestr,tmp,sizeof timestr);
+		}
+		if (runtime.tm_yday != 0) {
+		    snprintf(tmp,sizeof tmp,"+%dd",runtime.tm_yday);
+		    strlcat(timestr,tmp,sizeof timestr);
+		}
+		if (runtime.tm_hour != 0 || runtime.tm_min != 0) {
+		    strftime(tmp, sizeof tmp, "+%X", &runtime);
+		    strlcat(timestr,tmp,sizeof timestr);
+		}
+	    }
+	} else {
+	    runtime = *localtime(&runtimer);
+	    strftime(timestr, TIMESIZE, "%X %x", &runtime);
+	}
 	if (first) {
 	    printf("Date\t\t\tOwner\tQueue\tJob#\n");
 	    first=0;
 	}
 	pw = getpwuid(buf.st_uid);
 
-	printf("%s\t%s\t%c%s\t%ld\n", 
+	printf("%-18s\t%s\t%c%s\t%ld\n", 
 	       timestr, 
 	       pw ? pw->pw_name : "???", 
 	       queue, 
@@ -540,8 +571,13 @@
 	    perr("cannot stat in " ATJOB_DIR);
 	PRIV_END
 
-	if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
-	    continue;
+	if (dirent->d_name[0] == '_') {
+	    if(sscanf(dirent->d_name, "_%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
+		continue;
+	} else {
+	    if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
+		continue;
+	}
 
 	for (i=optind; i < argc; i++) {
 	    if (atoi(argv[i]) == jobno) {
@@ -724,7 +760,7 @@
 
     case AT:
 	timer = parsetime(argc, argv);
-	if (atverify)
+	if (atverify && !reboot_time)
 	{
 	    struct tm *tm = localtime(&timer);
 	    fprintf(stderr, "%s\n", asctime(tm));
Index: usr.bin/at/at.man
===================================================================
RCS file: /cvs/FreeBSD/src/usr.bin/at/at.man,v
retrieving revision 1.19
diff -u -r1.19 at.man
--- usr.bin/at/at.man	2001/07/10 14:15:54	1.19
+++ usr.bin/at/at.man	2001/07/27 00:45:24
@@ -106,13 +106,20 @@
 .Em today
 and to run the job tomorrow by suffixing the time with
 .Em tomorrow .
+And finally, you can give a time of
+.Em reboot
+or
+.Em reboot + Ar count \%time-units
+to have the job run some time after the next reboot.
 .Pp
 For example, to run a job at 4pm three days from now, you would do
 .Nm at Ar 4pm + 3 days ,
 to run a job at 10:00am on July 31, you would do
-.Nm at Ar 10am Jul 31
-and to run a job at 1am tomorrow, you would do
-.Nm at Ar 1am tomorrow .
+.Nm at Ar 10am Jul 31 ,
+to run a job at 1am tomorrow, you would do
+.Nm at Ar 1am tomorrow
+and to run a job an hour after the next reboot, you would do
+.Nm at Ar reboot + 1 hour .
 .Pp
 For both
 .Nm
@@ -267,6 +274,17 @@
 If this is the case for your site, you might want to consider another
 batch system, such as
 .Em nqs .
+.Pp
+The
+.Em reboot
+specification when used with a month offset doesn't always work as expected.
+For example,
+.Nm at Ar reboot + 1 month
+will in fact be turned into
+.Nm at Ar now + 31 days
+when
+.Nm atrun Fl b
+is run even if the current month does not have 31 days.
 .Sh AUTHORS
 At was mostly written by
 .An Thomas Koenig Aq ig25@rz.uni-karlsruhe.de .
Index: libexec/atrun/atrun.c
===================================================================
RCS file: /cvs/FreeBSD/src/libexec/atrun/atrun.c,v
retrieving revision 1.16
diff -u -r1.16 atrun.c
--- libexec/atrun/atrun.c	2001/07/23 11:00:31	1.16
+++ libexec/atrun/atrun.c	2001/07/27 00:10:05
@@ -392,11 +392,14 @@
     char queue;
     time_t now, run_time;
     char batch_name[] = "Z2345678901234";
+    char job_name[] = "Q1234512345678";
     uid_t batch_uid;
     gid_t batch_gid;
     int c;
     int run_batch;
     double load_avg = LOADAVG_MX;
+    int boot = 0;
+    unsigned long boot_time;
 
 /* We don't need root privileges all the time; running under uid and gid daemon
  * is fine.
@@ -407,7 +410,7 @@
     openlog("atrun", LOG_PID, LOG_CRON);
 
     opterr = 0;
-    while((c=getopt(argc, argv, "dl:"))!= -1)
+    while((c=getopt(argc, argv, "bdl:"))!= -1)
     {
 	switch (c)
 	{
@@ -418,6 +421,10 @@
 		load_avg = LOADAVG_MX;
 	    break;
 
+	case 'b':
+	    boot++;
+	    break;
+
 	case 'd':
 	    debug ++;
 	    break;
@@ -449,6 +456,31 @@
     batch_uid = (uid_t) -1;
     batch_gid = (gid_t) -1;
 
+    if (boot) {
+	/* Scan the directory for jobs to run after reboot and rename them.
+	 */
+	boot_time = (unsigned long)now/60;
+
+	while ((dirent = readdir(spool)) != NULL) {
+	    if (stat(dirent->d_name,&buf) != 0)
+		perr("cannot stat in " ATJOB_DIR);
+	    if (!S_ISREG(buf.st_mode)) 
+		continue;
+	    if (debug)
+		printf ("file: %s\n", dirent->d_name);
+	    if (sscanf(dirent->d_name,"_%c%5lx%8lx",&queue,&jobno,&ctm) != 3)
+		continue;
+	    ctm += boot_time;
+	    snprintf(job_name, sizeof(job_name), "%c%05lx%08lx",queue,
+		    jobno,ctm);
+	    if (rename(dirent->d_name,job_name) != 0)
+		perr("cannot rename job");
+	}
+	if (debug)
+	    printf ("\n");
+	rewinddir(spool);
+    }
+
     while ((dirent = readdir(spool)) != NULL) {
 	if (stat(dirent->d_name,&buf) != 0)
 	    perr("cannot stat in " ATJOB_DIR);
@@ -458,9 +490,18 @@
 	if (!S_ISREG(buf.st_mode)) 
 	    continue;
 
+	if (debug)
+	    printf ("file: %s\n", dirent->d_name);
+
+	if (dirent->d_name[0] == '_')
+	    continue;
+
 	if (sscanf(dirent->d_name,"%c%5lx%8lx",&queue,&jobno,&ctm) != 3)
 	    continue;
 
+	if (debug)
+	    printf ("\t\tqueue %c, job %ld time %ld\n", queue, jobno, ctm);
+
 	run_time = (time_t) ctm*60;
 
 	if ((S_IXUSR & buf.st_mode) && (run_time <=now)) {
@@ -494,9 +535,9 @@
 usage()
 {
     if (debug)
-	fprintf(stderr, "usage: atrun [-l load_avg] [-d]\n");
+	fprintf(stderr, "usage: atrun [-l load_avg] [-bd]\n");
     else
-	syslog(LOG_ERR, "usage: atrun [-l load_avg] [-d]"); 
+	syslog(LOG_ERR, "usage: atrun [-l load_avg] [-bd]"); 
 
     exit(EXIT_FAILURE);
 }
Index: libexec/atrun/atrun.man
===================================================================
RCS file: /cvs/FreeBSD/src/libexec/atrun/atrun.man,v
retrieving revision 1.10
diff -u -r1.10 atrun.man
--- libexec/atrun/atrun.man	2001/07/10 10:49:45	1.10
+++ libexec/atrun/atrun.man	2001/07/27 00:33:15
@@ -18,14 +18,39 @@
 .Xr crontab 5
 file
 .Pa /etc/crontab
-has to contain the line
+has to contain the lines
 .Bd -literal
 */5     *       *       *       *       root    /usr/libexec/atrun
+@reboot                                 root    /usr/libexec/atrun -b
 .Ed
 .Pp
 so that
 .Xr atrun 8
-gets invoked every five minutes.
+gets invoked every five minutes
+plus once on reboot with the 
+.Fl b
+option.
+.Pp
+If the
+.Fl b
+option is specified then
+.Nm
+looks for jobs queued using the
+.Em reboot
+time specification of
+.Xr at 1
+and changes them into normal jobs with the time offset from the current
+time.
+For example, a job originally queued with
+.Dq at roboot + 5 minutes
+would be requeued as if
+.Dq at now + 5 minutes
+were used with
+.Em now
+being the time
+.Nm
+is run with
+.Fl b .
 .Pp
 At every invocation, 
 .Nm
Index: etc/crontab
===================================================================
RCS file: /cvs/FreeBSD/src/etc/crontab,v
retrieving revision 1.31
diff -u -r1.31 crontab
--- etc/crontab	2001/02/19 02:47:41	1.31
+++ etc/crontab	2001/07/27 00:46:55
@@ -9,6 +9,7 @@
 #minute	hour	mday	month	wday	who	command
 #
 */5	*	*	*	*	root	/usr/libexec/atrun
+@reboot					root	/usr/libexec/atrun -b
 #
 # save some entropy so that /dev/random can reseed on boot
 */11	*	*	*	*	operator /usr/libexec/save-entropy

--y2zxS2PfCDLh6JVG--

--1Ow488MNN9B9o/ov
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (FreeBSD)

iEYEARECAAYFAjtgwSUACgkQWqkc/T0razToOACfZCL3yOFTlTl/pNcOuvl+ZKjs
jjEAoK4c3xyfuWVHdmM9IhQLtjTWV2I9
=8ilv
-----END PGP SIGNATURE-----

--1Ow488MNN9B9o/ov--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010726211728.B89345>