在C中读取一个不断更新的文件并等待新数据写入文件

Read a continuously updated file and wait for new data to be written to the file in C

我有一个日志文件,我想用 C 编写一个程序来读取该日志文件并在到达 EOF 时等待新数据。 我不想在我的代码中使用 tail -f。 我尝试了以下代码,但它不起作用:

#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <unistd.h>

#define PATH "/home/sanket/demo.txt"

int main(void)
{
        FILE * fp;
    int fd;
    char * line = NULL;
    size_t len = 0;
    ssize_t read1;
    int notify_fd;
    int wd,length ,i=0;
    char buffer[EVENT_BUF_LEN];

    fp = fopen(PATH, "r");
    if (fp == NULL)
            exit(EXIT_FAILURE);

    fd = fileno(fp);
    while (1)
    {
            read1 = getline(&line, &len, fp);
            if(read1 != -1)
                    printf("%s",line);
            else
            {
                    lseek(fd,0,SEEK_DATA);
            }
    }

    if (line)
            free(line);
    exit(EXIT_SUCCESS);
}

当您到达文件的第一个结尾时,设置 EOF 的输入流标志。在恢复操作之前必须清除它 (clearerr(fp))。你也应该正常睡觉。 (在与流关联的文件描述符上使用 lseek() 无济于事。)

这是一个基于您的代码的程序 — 我不得不更改 PATH 的值(这不是一个特别好的名字):

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

#define PATH "demo.txt"

int main(void)
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;

    fp = fopen(PATH, "r");
    if (fp == NULL)
    {
        perror(PATH);
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        if (getline(&line, &len, fp) != -1)
            printf("%s",line);
        else
        {
            printf("EOF\n");
            sleep(1);
            clearerr(fp);
        }
    }

    if (line)
        free(line);
    return(EXIT_SUCCESS);
}

如果您有将数据生成到文件的程序,您可以使用它进行测试。我有一个程序 dribbler 可以做到这一点:

$ dribbler -f demo.txt -s 1.5 -r 0.5 &
[1] 20678
$ cat demo.txt
0: message written to file
1: message written to file
2: message written to file
$ tail11
0: message written to file
1: message written to file
2: message written to file
3: message written to file
4: message written to file
5: message written to file
EOF
6: message written to file
EOF
EOF
7: message written to file
EOF
8: message written to file
EOF
EOF
9: message written to file
EOF
10: message written to file
EOF
11: message written to file
EOF
EOF
^C
$

dribbler的选项是:

Usage: dribbler [-hlntV][-s nap.time][-r std.dev][-f outfile][-i infile][-m message][-o openstr][-F format]
  -V           Print version information and exit
  -f outfile   Write to named file (dribbler.out)
  -h           Print this help message and exit
  -i infile    Read lines from input file
  -l           Loop back to start of input file on EOF
  -m message   Write message on each line of output
  -n           Number lines read from input file
  -o openstr   Flags passed to fopen() (a+)
  -s nap.time  Sleep for given interval between writes (1.000 second)
  -r std.dev   Randomize the time (Gaussian around nap.time with std.dev)
  -t           Write to standard output instead of file
  -F format    Printf format to use instead of %zu

因此,它以平均 1.5 秒的时间写入文件 demo.txt,服从标准差为 0.5 秒的高斯随机分布。 这就是为什么有时在连续的输出行之间有 2 EOF 条消息。