【问题标题】:watching log file in C在 C 中查看日志文件
【发布时间】:2013-09-23 10:43:22
【问题描述】:

使用 python,我有一个守护进程以下列方式监视日志文件:

f = open(r'logfile.log', 'r')
while True:
    line = f.readline()
    if not line:
      time.sleep(1)
    else:
      # do something

问题是,如果“做某事”部分是用 C 编写的,它的执行速度会快得多。所以,我想在 C 中做同样的事情。如何用 C 编写类似的跟踪日志文件的方法?

以下只是抓取整个文件,并对每一行执行“某些操作”。相反,我只想在日志文件中附加新行来“做某事”:)

  FILE *fr;
  char line[100];
  fr = fopen ("logfile.log", "rt");
  while(fgets(line, 100, fr) != NULL){
      //do something
  }
  fclose(fr);

谢谢!

【问题讨论】:

  • “做某事”到底在做什么?
  • @Blender 没关系。想象一下它使用套接字,发送 shtuff,调用一个运行速度比 python/perl/bash 快 300 倍的函数 :)
  • 打开文件后可以查找到文件末尾。你想用 C 还是 Python 来做?
  • @joni in C :) 我怎么不会错过任何额外的行?想象一个 log4j 进程写入一个日志文件。我想尾随那个文件,并用新添加的行来做事
  • 您的C 代码将在日志文件没有短暂更新时退出,而您的 Python 代码将继续查找。你需要一个while (1) 循环。

标签: python c file loops logfile


【解决方案1】:

您可以使用fseek 函数跳转到文件中的特定偏移量。为避免跳过 Python 代码检测到的新行,python 中的部分应将查找偏移量传递给 C 代码。 (最好的方法取决于你如何调用 C 代码..)

long seek_offset = /* get offset from Python side */
fseek(fr, seek_offset, SEEK_SET);

【讨论】:

    【解决方案2】:

    你可以试试下面的代码:

    #include <stdio.h>
    int main()
    {
         mkfifo("tmpFifo");
         if(fork()==0)//to avoid the main program getting stuck at system()..
         {
              system("tail -f logfile.txt > tmpFifo");
              exit(0);
         }
         int fd = open("tmpFifo", O_RDONLY);
         char buff[1000];//set some length depending on the maximum string that gets 
                         //appended...
         int n;
         while((n=read(fd, buff, 1000))>0)
         {
             //do something... where 'n' stores the number of chars read...
         }
         close(fd);
         rm("tmpFifo");
         return 0;
    }
    

    如果您想编写代码而不是使用tail -f,this 可能会有所帮助。但是,我想这是最简单的解决方案。

    【讨论】:

    • system("tail -f logfile.txt &gt; tmpFifo"); 还会回来吗?调用的文档说,“在命令完成后返回”,但 tail -f 除非从某个地方收到 KILL 信号,否则不会完成。
    • 感谢您指出这一点。相应地更新了答案...编辑:您也可以改用exec 调用。为简单起见,我仍然更喜欢使用system()。
    【解决方案3】:

    我最初的回答是:“在类似 POSIX 的系统上,您可以使用select() 来“监视”打开的文件描述符以查看是否有更多输入可用。这可能是在任何 Unix/Linux 系统上执行此操作的规范方式。”,但 I was wrong。

    我在套接字和管道上使用了select(),并假设它只会在有更多可用数据时返回,但这可能是肤浅的直觉,但实际上并非如此:select() 被定义为返回当后续的read()(或write())不会阻塞时,这是另一回事,因为read()可能读取零字节而不是阻塞。

    普通文件总是read()-able,即使在文件末尾。如果您尝试使用select() 跟踪日志文件,select() 永远不会阻塞,随后的read()s 是零长度的。简而言之,你最终会忙于等待。阅读任何tail 实现的源代码,或阅读surrounding discussion 将确认这一点。

    我想我应该把它留在这里,以防其他人犯同样的错误。

    【讨论】:

      猜你喜欢
      • 2022-10-15
      • 2023-03-27
      • 2011-07-23
      • 2016-03-16
      • 2010-11-04
      • 2013-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多