使用 inotify 跟踪系统中的所有文件

Posted

技术标签:

【中文标题】使用 inotify 跟踪系统中的所有文件【英文标题】:Using inotify to keep track of all files in a system 【发布时间】:2012-05-10 05:21:41 【问题描述】:

问题:

inotify 可以用来在 [linux] 系统中可靠地记录文件吗?

详情:

我正在尝试使用 inotifywait 来跟踪用户的动作(目前使用 bash,但我已将 suggested 迁移到脚本语言)。最终我想在创建时向数据库添加新文件(createmoved_from),在文件修改时更新数据库中的现有行(modifyattribmove_to),最后删除一行文件删除时 (delete)。然而,我遇到了很多问题,因为即使像 save 这样看似简单的操作也会生成许多 inotifywait 消息。观察以下命令及其输出(注意,/home/user/ 的使用纯粹是出于示例目的):

示例:

示例 1:监听文件创建:

$ inotifywait -mr /home/user/ -e create  --format %w:%f:%e:%T --timefmt %T

触摸:

$touch test.txt
/home/user/:test.txt:CREATE:21:35:30

用 vim 打开一个新文件,然后发出 :w 命令:

$vim test2.txt
/home/user/:test2.txt:CREATE:21:35:30

用 vim 打开一个现有文件,然后发出 :w 命令:

$vim test2.txt
/home/user/:4913:CREATE:21:35:30
/home/user/:test2.txt:CREATE:21:35:30

用 gedit 打开一个新文件,然后点击保存:

$gedit test3.txt
/home/user/:test3.txt~:CREATE:21:35:30

使用 gedit 打开现有文件,然后点击保存:

$gedit test3.txt
/home/user/:.goutputstream-HN3ZDW:CREATE:21:35:30
/home/user/:test3.txt~:CREATE:21:35:30

请注意,不仅两个新文件显示为已创建(4913.goutputstream-HN3ZDW),而且唯一正在创建的文件是 test3.txt~not test3.txt ,即使在使用ls 命令检查时创建了文件test3.txt。为了完整起见,这里是上面的示例,但还有更多选项。

示例 1:监听文件创建、修改、删除和移动:

$ inotifywait -mr /home/user/ -e create -e modify -e delete -e moved_to -e moved_from --format %w:%f:%e:%T --timefmt %T

触摸:

$touch test.txt
/home/user/:test.txt:CREATE:21:35:30

用 vim 打开一个新文件,然后发出 :w 命令:

$vim test2.txt
/home/user/:test2.txt:CREATE:22:12:32

用 vim 打开一个现有文件,然后发出 :w 命令:

$vim test2.txt
/home/user/:4913:CREATE:22:04:35
/home/user/:4913:DELETE:22:04:35
/home/user/:test2.txt:MOVED_FROM:22:04:35
/home/user/:test2.txt~:MOVED_TO:22:04:35
/home/user/:test2.txt:CREATE:22:04:35
/home/user/:test2.txt~:DELETE:22:04:35

用 gedit 打开一个新文件,然后点击保存:

$gedit test3.txt
/home/user/:test3.txt~:CREATE:21:35:30

使用 gedit 打开现有文件,然后点击保存:

$gedit test3.txt
/home/user/:.goutputstream-0WQ2DW:CREATE:22:06:34
/home/user/:test3.txt~:CREATE:22:06:34
/home/user/:.goutputstream-0WQ2DW:MOVED_FROM:22:06:34
/home/user/:test3.txt:MOVED_TO:22:06:34

基本上我的问题是“是否可以使用inotify 更新数据库中的文件”?例如,如果用户编辑一个文件并保存它,我希望它作为对该文件的更新反映在数据库中,而不是一个全新的文件替换一个完全不同的文件。任何帮助都将不胜感激,即使这是一个将我指向不同方向的建议。

【问题讨论】:

【参考方案1】:

inotify 告诉你发生了什么。

Gedit 与大多数编辑器一样,通过先写入一个临时文件然后将该文件移动到适当位置来进行保存。这样可以避免在写入文件时编辑器或整个系统崩溃的情况下用半写版本覆盖文件。 Vim 采用了不同的方法(这可以配置,我不会在这里详细介绍 - 参见例如 why inode value changes when we edit in “vi” editor?):它首先创建一个临时备份文件,然后写入新文件。

如果您希望将这些记录为单个编辑事件,则必须对偶数日志执行一些模式识别。替换现有文件的创建-写入-移动序列和类似 vim 的创建-移动-创建删除序列将是原型模式。请注意,该模式可能与其他事件交错。

我怀疑有更好的方法来做你想做的事,但我不明白你想做什么。如果您尝试记录用户操作,您已经找到了一种方法,但还有更简单的方法:loggedfs or the audit subsystem。如果要保留所有文件版本的备份,请将编辑器连接到版本控制系统(这使用户可以控制备份的内容)或使用versioning filesystem,例如copyfs。您甚至可以使用mysqlfs 或postgresqlfs 之类的文件系统将文件直接存储在数据库中(诚然,这两个项目看起来都没有维护)。

【讨论】:

感谢您的信息。 wrt。模式识别,我担心它不会 100% 可靠。我要做的是将所有用户和组权限存储在 MySQL 中,以及所有文件位置(不是实际文件),我希望系统中的所有更新都反映在数据库中。我去看看mysqlfs。 @puk 好吧,那么 mysqlfs、copyfs 之类的就帮不了你了。 Loggedfs 或审计日志是要走的路(它们比 inotify 日志更容易被利用)。你会在事件发生时得到它们。您在这些事件上赋予了高级含义,但在文件系统级别,这些含义没有对应物:编辑器知道“保存文件”的概念,但文件系统只能看到打开、写入、重命名等. 由于高级含义来自您,您需要进行分析以识别实际事件中有意义的模式。 谢天谢地,mysqlfs 页面看起来像是在 1992 年编码的。我将看看loggedfs 和审计。当您说“日志”时,我假设您的意思是来自inotifywait 的信号,对吗?还是您的意思是实际写入日志文件? 只需添加--exclude '/\..+',inotify 将忽略临时 .goutputstream 文件

以上是关于使用 inotify 跟踪系统中的所有文件的主要内容,如果未能解决你的问题,请参考以下文章

Inotify: 高效实时的Linux文件系统事件监控框架

linux 监视文件系统inotify 测试

Inotify与Android文件监控FileObserver原理

如何在功能测试中模拟 INotify 失败?

rsync+inotify实时同步

iOS - 提交更新到仓库(分布式版本控制系统)