[patch] making dump(8) work with cron(8)

Gunther Schadow gunther at aurora.regenstrief.org
Thu Dec 13 23:33:31 PST 2007


Hi, please take note of the attached patch and consider 
applying it for good. It addresses a long known bug 
described in man dump(8):

BUGS
     [...] Since dumps are often done in an unattended fashion using
     cron(8) jobs asking for Operator intervention would result in the dump
     dying.  However, there is nothing wrong with a dump tape written when
     this sort of read error occurs, and there is no reason to terminate the
     dump.

the attached patch fixes it: adding 2 options [-Y | -N]

     -Y      Do not require a tty, do not ask any questions but answer all
             questions with "yes".

     -N      Do not require a tty, do not ask any questions but answer all
             questions with "no".

     In order to use dump with cron(8), the -Y or -N options can be used to
     tell dump not to require a tty for getting questions answered, but
     instead to assume "yes" ( -Y ) or "no" ( -N ) respectively.

I considered an alternative making dump use stdio rather than 
forging fopen a /dev/tty. This would allow someone to use some
expect like remote control logic or one could have piped it with
yes(1) or no(1). But I went with the simpler option for now.

regards,
-Gunther

-- 
Gunther Schadow, M.D., Ph.D.                  gschadow at regenstrief.org
Associate Professor           Indiana University School of Informatics
Regenstrief Institute, Inc.      Indiana University School of Medicine
tel:1(317)423-5521                       http://aurora.regenstrief.org
-------------- next part --------------
*** dump.h~	Thu Dec  2 08:56:53 2004
--- dump.h	Fri Dec 14 01:19:49 2007
***************
*** 87,92 ****
--- 87,93 ----
  long	dev_bsize;	/* block size of underlying disk device */
  int	dev_bshift;	/* log2(dev_bsize) */
  int	tp_bshift;	/* log2(TP_BSIZE) */
+ int     dontask;        /* don't use interactive terminal, answer all questions with yes (1) or no (-1) */
  
  /* operator interface functions */
  void	broadcast(const char *message);
*** main.c~	Mon Oct 16 07:52:00 2006
--- main.c	Fri Dec 14 01:13:29 2007
***************
*** 121,129 ****
  	if (argc < 2)
  		usage();
  
  	obsolete(&argc, &argv);
  	while ((ch = getopt(argc, argv,
! 	    "0123456789aB:b:C:cD:d:f:h:LnP:Ss:T:uWw")) != -1)
  		switch (ch) {
  		/* dump level */
  		case '0': case '1': case '2': case '3': case '4':
--- 121,131 ----
  	if (argc < 2)
  		usage();
  
+ 	dontask = 0;
+ 
  	obsolete(&argc, &argv);
  	while ((ch = getopt(argc, argv,
! 	    "0123456789aB:b:C:cD:d:f:h:LnP:Ss:T:uWwYN")) != -1)
  		switch (ch) {
  		/* dump level */
  		case '0': case '1': case '2': case '3': case '4':
***************
*** 217,222 ****
--- 219,232 ----
  			lastdump(ch);
  			exit(X_FINOK);	/* do nothing else */
  
+ 		case 'Y':
+ 		  dontask = 1;
+ 		  break;
+ 
+ 		case 'N':
+ 		  dontask = -1;
+ 		  break;
+ 		  
  		default:
  			usage();
  		}
***************
*** 588,594 ****
  usage(void)
  {
  	fprintf(stderr,
! 		"usage: dump [-0123456789acLnSu] [-B records] [-b blocksize] [-C cachesize]\n"
  		"            [-D dumpdates] [-d density] [-f file | -P pipecommand] [-h level]\n"
  		"            [-s feet] [-T date] filesystem\n"
  		"       dump -W | -w\n");
--- 598,604 ----
  usage(void)
  {
  	fprintf(stderr,
! 		"usage: dump [-0123456789acLnSu] [-Y|-N] [-B records] [-b blocksize] [-C cachesize]\n"
  		"            [-D dumpdates] [-d density] [-f file | -P pipecommand] [-h level]\n"
  		"            [-s feet] [-T date] filesystem\n"
  		"       dump -W | -w\n");
*** optr.c~	Wed Feb 16 01:48:35 2005
--- optr.c	Fri Dec 14 01:19:24 2007
***************
*** 78,116 ****
  {
  	char	replybuffer[64];
  	int	back, errcount;
! 	FILE	*mytty;
  
! 	if ((mytty = fopen(_PATH_TTY, "r")) == NULL)
! 		quit("fopen on %s fails: %s\n", _PATH_TTY, strerror(errno));
! 	attnmessage = question;
! 	timeout = 0;
! 	alarmcatch(0);
! 	back = -1;
! 	errcount = 0;
! 	do {
! 		if (fgets(replybuffer, 63, mytty) == NULL) {
! 			clearerr(mytty);
! 			if (++errcount > 30)	/* XXX	ugly */
! 				quit("excessive operator query failures\n");
! 		} else if (replybuffer[0] == 'y' || replybuffer[0] == 'Y') {
! 			back = 1;
! 		} else if (replybuffer[0] == 'n' || replybuffer[0] == 'N') {
! 			back = 0;
! 		} else {
! 			(void) fprintf(stderr,
! 			    "  DUMP: \"Yes\" or \"No\"?\n");
! 			(void) fprintf(stderr,
! 			    "  DUMP: %s: (\"yes\" or \"no\") ", question);
! 		}
! 	} while (back < 0);
  
! 	/*
! 	 *	Turn off the alarm, and reset the signal to trap out..
! 	 */
! 	(void) alarm(0);
! 	if (signal(SIGALRM, sig) == SIG_IGN)
! 		signal(SIGALRM, SIG_IGN);
! 	(void) fclose(mytty);
  	return(back);
  }
  
--- 78,124 ----
  {
  	char	replybuffer[64];
  	int	back, errcount;
! 	FILE	*mytty = NULL;
  
! 	if(!dontask) {
! 	  if ((mytty = fopen(_PATH_TTY, "r")) == NULL)
! 	    quit("fopen on %s fails: %s\n", _PATH_TTY, strerror(errno));
! 	  attnmessage = question;
! 	  timeout = 0;
! 	  alarmcatch(0);
! 	  back = -1;
! 	  errcount = 0;
  
! 	  do {
! 	    if (fgets(replybuffer, 63, mytty) == NULL) {
! 	      clearerr(mytty);
! 	      if (++errcount > 30)	/* XXX	ugly */
! 		quit("excessive operator query failures\n");
! 	    } else if (replybuffer[0] == 'y' || replybuffer[0] == 'Y') {
! 	    back = 1;
! 	    } else if (replybuffer[0] == 'n' || replybuffer[0] == 'N') {
! 	      back = 0;
! 	    } else {
! 	      (void) fprintf(stderr,
! 			     "  DUMP: \"Yes\" or \"No\"?\n");
! 	      (void) fprintf(stderr,
! 			     "  DUMP: %s: (\"yes\" or \"no\") ", question);
! 	    }
! 	  } while (back < 0);
! 
! 	  /*
! 	   *	Turn off the alarm, and reset the signal to trap out..
! 	   */
! 	  (void) alarm(0);
! 	  if (signal(SIGALRM, sig) == SIG_IGN)
! 	    signal(SIGALRM, SIG_IGN);
! 	  (void) fclose(mytty);
! 	  
! 	} else if(dontask == 1)
! 	  back = 1;
! 	else if(dontask == -1)
! 	  back = 0;
! 	
  	return(back);
  }
  
*** dump.8~	Wed Aug 23 08:42:22 2006
--- dump.8	Fri Dec 14 01:43:25 2007
***************
*** 39,44 ****
--- 39,45 ----
  .Sh SYNOPSIS
  .Nm
  .Op Fl 0123456789acLnSu
+ .Op Fl Y | Fl N
  .Op Fl B Ar records
  .Op Fl b Ar blocksize
  .Op Fl C Ar cachesize
***************
*** 258,263 ****
--- 259,270 ----
  .Dq operator
  by means similar to a
  .Xr wall 1 .
+ .It Fl Y
+ Do not require a tty, do not ask any questions but
+ answer all questions with "yes".
+ .It Fl N
+ Do not require a tty, do not ask any questions but
+ answer all questions with "no".
  .It Fl S
  Display an estimate of the backup size and the number of
  tapes required, and exit without actually performing the dump.
***************
*** 403,408 ****
--- 410,430 ----
  is busy,
  and will be for some time.
  .Pp
+ In order to use dump with
+ .Xr cron 8 , 
+ the
+ .Fl Y
+ or 
+ .Fl N
+ options can be used to tell
+ .Nm
+ not to require a tty for getting questions answered, but instead
+ to assume "yes" (
+ .Fl Y
+ ) or "no" (
+ .Fl N
+ ) respectively.
+ .Pp
  In the event of a catastrophic disk event, the time required
  to restore all the necessary backup tapes or files to disk
  can be kept to a minimum by staggering the incremental dumps.
***************
*** 493,506 ****
  on mounted partitions if the file system is being modified while the
  .Nm
  is running.
- Since dumps are often done in an unattended fashion using
- .Xr cron 8
- jobs asking for Operator intervention would result in the
- .Nm
- dying.
- However, there is nothing wrong with a dump tape written when this sort
- of read error occurs, and there is no reason to terminate the
- .Nm .
  .Pp
  Each reel requires a new process, so parent processes for
  reels already written just hang around until the entire tape
--- 515,520 ----


More information about the freebsd-bugs mailing list