Я на самом деле реализую очень простую версию хвоста (1). Во FreeBSD я использую kqueue
для мониторинга файла для изменений, а затем для добавления добавленных строк в вывод. Но это не переносимый способ, так как kqueue
доступен только в семействе BSD. Существует ли общий, эффективный и независимый от платформы способ мониторинга файлов для изменений в UNIX? Я предпочитаю не использовать внешние библиотеки.переносной способ мониторинга файла для изменений
Это код, который я написал:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
void die(const char*);
#define MAXLINE 1024
int main(int argc, char *argv[])
{
int fdes;
int kq;
int nev;
int flags;
off_t curoff;
char line[MAXLINE + 1];
ssize_t nbytes;
struct kevent change, event;
if (2 != argc)
{
fprintf(stderr, "Usage: %s path\n", argv[0]);
exit(EXIT_FAILURE);
}
if (-1 == (fdes = open(argv[1], O_RDONLY)))
die("open()");
if (-1 == (curoff = lseek(fdes, 0, SEEK_END)))
die("lseek()");
int ch = 0;
int i = 0;
while (i < 10)
{
read(fdes, &ch, 1);
if (ch == '\n')
i++;
if (10 > i)
lseek(fdes, --curoff, SEEK_SET);
}
if (-1 == (flags = fcntl(fdes, F_GETFL)))
die("fcntl()");
flags |= O_NONBLOCK;
if (-1 == fcntl(fdes, F_SETFL, flags))
die("fcntl()1");
while ((nbytes = read(fdes, line, MAXLINE)) > 0)
if (write(STDOUT_FILENO, line, nbytes) != nbytes)
die("write()");
if (-1 == (kq = kqueue()))
die("kqueue()");
EV_SET(&change, fdes, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
NOTE_EXTEND | NOTE_WRITE | NOTE_DELETE, 0, NULL);
if (-1 == kevent(kq, &change, 1, NULL, 0, NULL))
die("kevent()");
for (;;)
{
if (-1 == (nev = kevent(kq, NULL, 0, &event, 1, NULL)))
die("kevent()");
if (nev > 0)
{
if (event.fflags & NOTE_WRITE || event.fflags & NOTE_EXTEND)
{
while ((nbytes = read(fdes, line, MAXLINE)) > 0)
if (write(STDOUT_FILENO, line, nbytes) != nbytes)
die("write()");
}
else if (NOTE_DELETE & event.fflags)
{
printf("The file has been deleted\n");
break;
}
}
}
return 0;
}
void die(const char *str)
{
perror(str);
exit(EXIT_FAILURE);
}
Самый портативный способ - опросить все файлы и искать изменения в временной шкале изменения файлов (используя, например, ['stat'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatat.html)). Я бы не назвал это эффективным, хотя и, конечно, не будет работать для файлов в файловых системах, у которых нет метки времени модификации (хотя в наши дни это должно быть немного и далеко друг от друга). –