Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Feb 1998 09:17:37 -0800 (PST)
From:      Curt Sampson <cjs@netbsd.org>
To:        freebsd-hackers@FreeBSD.ORG, support@bsdi.com
Subject:   tail -F patches
Message-ID:  <Pine.NEB.3.96.980210090527.5139A-100000@cynic.portal.ca>

next in thread | raw e-mail | index | archive | help
This was really popular with the NetBSD crowd, so I thought I'd
forward it on to you folks.

The following patches to tail(1) add a -F option which will make
it continue to follow data appended to a file even if the file is
rotated by newsyslog(8) or something similar, or truncated.

cjs

Curt Sampson    cjs@portal.ca	   Info at http://www.portal.ca/
Internet Portal Services, Inc.	   Through infinite mist, software reverberates
Vancouver, BC  (604) 257-9400	   In code possess'd of invisible folly.


Index: forward.c
===================================================================
RCS file: /cvsroot/src/usr.bin/tail/forward.c,v
retrieving revision 1.8
diff -u -r1.8 forward.c
--- forward.c	1997/10/19 23:45:08	1.8
+++ forward.c	1998/02/09 19:21:43
@@ -91,6 +91,15 @@
 {
 	int ch;
 	struct timeval second;
+	int dostat = 0;
+	struct stat statbuf;
+	off_t lastsize = 0;
+	dev_t lastdev;
+	ino_t lastino;
+
+	/* Keep track of file's previous incarnation. */
+	lastdev = sbp->st_dev;
+	lastino = sbp->st_ino;
 
 	switch(style) {
 	case FBYTES:
@@ -166,9 +175,11 @@
 	}
 
 	for (;;) {
-		while ((ch = getc(fp)) != EOF)
+		while ((ch = getc(fp)) != EOF)  {
+			lastsize++;	/* track size changes between stats */
 			if (putchar(ch) == EOF)
 				oerr();
+		}
 		if (ferror(fp)) {
 			ierr();
 			return;
@@ -186,6 +197,39 @@
 		if (select(0, NULL, NULL, NULL, &second) == -1)
 			err(1, "select: %s", strerror(errno));
 		clearerr(fp);
+
+		if (fflag == 1)
+			continue;
+		/*
+		 * We restat the original filename every five seconds. If
+		 * the size is ever smaller than the last time we read it,
+		 * the file has probably been truncated; if the inode or
+		 * or device number are different, it has been rotated.
+		 * This causes us to close it, reopen it, and continue
+		 * the tail -f. If stat returns an error (say, because
+		 * the file has been removed), just continue with what
+		 * we've got open now.
+		 */
+		if (dostat > 0)  {
+			dostat -= 1;
+		} else {
+			dostat = 5;
+			if (stat(fname, &statbuf) == 0)  {
+				if (statbuf.st_dev != lastdev ||
+				    statbuf.st_ino != lastino ||
+				    statbuf.st_size < lastsize)  {
+					lastdev = statbuf.st_dev;
+					lastino = statbuf.st_ino;
+					lastsize = 0;
+					fclose(fp);
+					if ((fp = fopen(fname, "r")) == NULL)
+						err(1, "can't reopen %s: %s",
+						    fname, strerror(errno));
+				} else {
+					lastsize = statbuf.st_size;
+				}
+			}
+		}
 	}
 }
 
Index: tail.1
===================================================================
RCS file: /cvsroot/src/usr.bin/tail/tail.1,v
retrieving revision 1.5
diff -u -r1.5 tail.1
--- tail.1	1997/10/19 23:45:11	1.5
+++ tail.1	1998/02/09 19:21:44
@@ -44,7 +44,11 @@
 .Nd display the last part of a file
 .Sh SYNOPSIS
 .Nm
-.Op Fl f Li | Fl r
+.Oo
+.Fl f |
+.Fl F |
+.Fl r
+.Oc
 .Oo
 .Fl b Ar number |
 .Fl c Ar number |
@@ -93,6 +97,21 @@
 The
 .Fl f
 option is ignored if the standard input is a pipe, but not if it is a FIFO.
+.It Fl F
+The
+.Fl F
+option is the same as the
+.Fl f
+option, except that every five seconds
+.Nm
+will check to see if the file named on the command line has been
+shortened or moved (it is considered moved if the inode or device
+number changes) and, if so, it will close
+the current file, open the filename given, print out the entire
+contents, and continue to wait for more data to be appended.
+This option is used to follow log files though rotation by
+.Xr newsyslog 8
+or similar programs.
 .It Fl n Ar number
 The location is
 .Ar number
Index: tail.c
===================================================================
RCS file: /cvsroot/src/usr.bin/tail/tail.c,v
retrieving revision 1.5
diff -u -r1.5 tail.c
--- tail.c	1997/10/19 23:45:11	1.5
+++ tail.c	1998/02/09 19:21:44
@@ -111,8 +111,11 @@
 
 	obsolete(argv);
 	style = NOTSET;
-	while ((ch = getopt(argc, argv, "b:c:fn:r")) != -1)
+	while ((ch = getopt(argc, argv, "Fb:c:fn:r")) != -1)
 		switch(ch) {
+		case 'F':
+			fflag = 2;
+			break;
 		case 'b':
 			ARG(512, FBYTES, RBYTES);
 			break;
@@ -136,7 +139,7 @@
 	argv += optind;
 
 	if (fflag && argc > 1)
-		err(1, "-f option only appropriate for a single file");
+		err(1, "-f and -F options only appropriate for a single file");
 
 	/*
 	 * If displaying in reverse, don't permit follow option, and convert


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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96.980210090527.5139A-100000>