0

I'm trying to implement a solution in pure C to monitor new entries made to log file that records a high volume of requests to a web service.

I would like something like tail -f, where a change in the log file results in my process getting the new changes instantly.

This needs to run on Solaris 10, unfortunately.

I know this question has been asked and answered in other threads, but none of the solutions acceptable for my situation

1) The solution must not require super user access in any way. As this is a enterprise production environment, no superuser access is available to me on this system, so I can't do something like install a driver.

2) The log file will be very large. Parsing it entirely, repeatedly for new changes is not acceptable.

It seems to me that if I can run tail -f as a non-privileged user, I should be able to do the same programmatically as the same user. I realize a nice hack would be to pipe the output from tail -f into my process, though I would like something cleaner.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Mike
  • 58,961
  • 76
  • 175
  • 221

1 Answers1

2

This is very straightforward - just read, and if you read zero bytes, wait for a specified time. Just for illustration (open your own files and improve buffer and error handling to taste). I have edited this to show where error handling and seeking the last lines should occur, and fixed the position of the sleep(). This is by no means a complete example, just an indication of how things could be done.

#include <unistd.h>
#include <stdio.h>

#define NBUF 1024
int main()
{
  char buf[NBUF];
  ssize_t rcount, wcount;

  int fin = 0, fout = 1;  /* Or use open.  */
  /* Code to display the last 10 lines goes here.  */
  while (1)
    {
      while ((rcount = read (fin, buf, NBUF)) > 0)
    {
      wcount = write (fout, buf, rcount);
      if (wcount != rcount)
        {
          perror("write didn't work.");
          /* Handle error here, exit() or whatever.  */
        }
    }
      if (rcount == -1)
        {
           perror("Read didn_t work...");
           /* Handle error here, exit() or something else.  */
      sleep (1);
    }
}
  • There are a couple of issues here, AFAICS. (1) You display the whole of the input, not just the last ten lines, and (2) You wait a second between read operations, which is fine if the input is less than one buffer-full per second, but not so hot if the input rate is higher (and 1 KiB/s is not a high speed input). You only sleep if a read returns 0 bytes, I think. If the read fails (`rcount == -1`), you should probably exit the loop. The 'last ten lines' behaviour is the standard for `tail` and leads to interesting discussions when the file is gigabytes long. – Jonathan Leffler Mar 28 '15 at 20:37
  • 2
    @Johathan Leffler: Your're right, this is not a comprehensive example, this just shows the principle how to show trailing output. I didn't mean to write a complete tail(1) program, that is available from GNU coreutils. –  Mar 28 '15 at 23:33