如何在Linux中使用inode创建新文件时获取带绝对路径的文件名?

3
我正在进行一些与我的Linux操作系统(CentOS)相关的实验,并且我想跟踪在相同环境下创建的所有工具日志。工具会生成相应的日志(.log扩展名),为了跟踪这些更改,我编写了一个Perl watcher,它实际上监视我设置的目录,并在创建新文件时显示输出。但是这会消耗大量内存和CPU利用率,因为我将2秒作为睡眠周期。
我的问题是:“有没有更好的方法来做到这一点?”我考虑使用inode表来跟踪系统中的所有更改。这样能解决我的问题吗?如果是,则请告诉我们解决方案。

zdim,听到这些模块很不错。Vikas,不确定你是否正在寻找zdim建议的通用文件系统监视器。如果你能分享你的Perl代码,也许我们可以弄清楚为什么它会消耗这么多内存和CPU。 - codeforester
1个回答

9
看起来您想要监视一个目录的变化。这是一项复杂的工作,但有很好的模块可以使用。最简单推荐的一个可能是Linux::Inotify2

该模块实现了与 Linux 2.6.13 及更高版本的 Inotify 文件/目录变更通知系统的接口。

看起来这就是你需要的东西。
任何这样的监视都需要额外的事件处理。本示例使用AnyEvent
use warnings;
use strict;
use feature 'say';

use AnyEvent;
use Linux::Inotify2;

my $dir = 'dir_to_watch';

my $inotify = Linux::Inotify2->new  or die "Can't create inotify object: $!";

$inotify->watch( $dir, IN_MODIFY | IN_CREATE, sub {
    my $e = shift;
    my $name = $e->fullname;
    say "$name modified" if $e->IN_MODIFY;    # Both show the new file
    say "$name created"  if $e->IN_CREATE;    # but see comments below
});

my $inotify_w = AnyEvent->io (
    fh => $inotify->fileno, poll => 'r', cb => sub { $inotify->poll }
);

1 while $inotify->poll;

如果您只关心文件,那么只需要一个常量以上。对于这两种类型的事件,$name都有新文件的名称。据我所在系统上man inotify的介绍,返回的inotify_event结构中的name字段标识了目录内的文件名。适当表示inotify_event结构的对象是Linux::Inotify2::Watcher
使用IN_CREATE似乎是您的目的的明显解决方案。我测试了在同一命令行上创建两个文件,并使用分号分隔的两个重定向echo命令,以及通过touch创建文件。写入的文件被检测为单独的事件,touch的文件也是如此。
使用IN_MODIFY也可能奏效,因为它监视了(在$dir中)所观察对象(始终为目录)中的任何文件系统对象,例如文件、目录、符号链接、设备节点等等。
对于测试来说,上述由echo编写的两个文件报告为单独的事件。但是touch的文件并没有报告,因为数据没有更改(文件没有被写入)。
哪种方法更适合您的需求取决于细节。例如,工具可能在启动时打开日志文件,但只有在以后才写入它。上述两种方法在这种情况下的行为将有所不同。所有这些都应该在特定条件下仔细研究。
我们可能会考虑竞争条件,因为当代码执行时,其他文件可能会溜进来。但是该模块要好得多,并且在处理程序完成后它确实会报告新更改。我通过在代码运行(和休眠)时创建文件来测试,并且它们被报告了。
一些其他值得注意的事件驱动编程框架包括POEIO::AsyncFile::Monitor也可以完成此类工作。

在我的脚本中,我使用File::Monitor来监视文件,但如果我运行脚本超过3天,它会消耗更多的CPU使用率。我想要一种方式,可以跟踪Linux的inode,这样当创建一个新的inode时,我就可以轻松地通过该inode获取文件名。那么,有没有办法跟踪一个inode呢? - vikas chib
@vikaschib 感谢您的反馈!这就是为什么我首先推荐 这个模块 - 它实现了 inotify 系统,这正是您所询问的。我不建议手动完成这个过程(除非出于乐趣)。至于增加的 CPU 使用量...听起来可能是该模块的问题?我建议:(1) 尝试使用这个模块 (2) 您能否安排脚本不要连续运行那么长时间?也许通过 cron 作业退出并重新启动 (3) 如果问题仍然存在,请发布另一个问题,因为那是另一回事。 - zdim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接