【问题标题】:Efficient way to continually read in data from a text file从文本文件中持续读取数据的有效方法
【发布时间】:2011-03-21 16:02:25
【问题描述】:

我们在 FTP 端点上有一个脚本,用于监控由我们的 FTP 守护程序发出的 FTP 日志。 目前我们所做的是让 perl 脚本在文件上运行一个 tail -F 并将每一行发送到远程 MySQL 数据库,根据记录类型,列内容略有不同。

此数据库包含 tarball 名称/内容的内容表,以及对所述包的 FTP 用户操作;下载、删除和所有其他 VSFTPd 日志。

我认为这特别糟糕,但我不确定哪个更好。

替换的目标仍然是尽可能快地将日志文件内容输入数据库。我正在考虑做一些事情,比如制作一个 FIFO/管道文件来代替 FTP 日志文件所在的位置,这样我就可以定期读取它一次,确保我不会两次读取相同的东西。假设 VSFTPd 会很好(我认为不会,欢迎洞察!)。

FTP 守护程序是 VSFTPd,我至少相当确定它们的日志记录能力范围是:xfer 样式日志、vsftpd 样式日志,两者都有,或者根本没有日志记录。

问题是,如果有的话,还有什么比我们已经在做的更好?

【问题讨论】:

    标签: perl logging ftp


    【解决方案1】:

    老实说,我认为你现在所做的并没有什么问题。 tail -f 非常高效。唯一真正的问题是,如果你的观察者脚本死了,它会失去状态(这是一个用旋转日志文件解决的半困难问题)。 CPAN 上还有一个不错的 File::Tail 模块,它可以让您免于脱壳,并提供一些不错的自定义功能。

    使用 FIFO 作为日志 可以 工作(只要 vsftpd 不尝试在任何时候取消链接并重新创建日志文件,它可能会这样做)但我发现它存在一个主要问题.如果没有人从 FIFO 的另一端读取数据(例如,如果您的脚本崩溃或从未启动),那么不久之后所有对 FIFO 的写入将开始阻塞。而且我还没有对此进行测试,但是日志文件写入阻塞很可能会导致 整个服务器 挂起。不是一个非常漂亮的场景。

    【讨论】:

    • Perl 模块和 CPAN 是我最好的朋友。尽管我指向 Net::FTP,我们还是从 perl 脚本中输出了 ftp 命令... ... ;_;顺便说一句,你的代表疯了。惊人的。社区成员应该渴望像你一样乐于助人。
    【解决方案2】:

    阅读不断更新的文件时遇到的问题是你想继续阅读,即使到达文件末尾也是如此。解决这个问题的方法是重新搜索到您在文件中的当前位置:

    寻找文件句柄, 0, 1;

    这是我做这种事情的代码:

    open(FILEHANDLE,'<', '/var/log/file') || die 'Could not open log file';
    seek(FILEHANDLE, 0, 2) || die 'Could not seek to end of log file';
    for (;;) {
    while (<FILEHANDLE>) {
        if ( $_ =~ /monitor status down/ ) {
                print "Gone down\n";
            }
        }
        sleep 1;
        seek FILEHANDLE, 0, 1;      # clear eof
    }  
    

    【讨论】:

      【解决方案3】:

      您应该研究 inotify(假设您使用的是一个不错的基于 posix 的操作系统),这样您就可以在日志文件更新时运行您的 perl 脚本。如果此级别的 IO 导致问题,您可以始终将日志文件保存在 RAMdisk 上,因此 IO 非常快。

      这应该可以帮助您进行设置: http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/

      【讨论】:

      • 这不是一个“预定警报”,因为日志文件的添加非常定期发生。假设...至少每 5 秒一次,每秒多次,其他时间每秒多次。这更多是关于如何最好地主动获取内容并将其发送到某个地方。 edit 同样,高效,并且给定条目仅一次
      【解决方案4】:

      您可以将文件作为管道打开。

      open(my $file, '-|', '/ftp/file/path');
      
      while (<$file>) {
          # you know the rest
      }
      

      File::Tail 做到了这一点,加上启发式睡眠和良好的错误处理和恢复。

      编辑:再想一想,如果你能管理它,一个真正的系统管道会更好。如果没有,您需要找到您放入数据库的最后一件事,并在文件中旋转,直到您在进程开始时找到您放入数据库的最后一件事。不是那么容易完成,如果你无法确定你离开的地方,可能是不可能的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多