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>