如何在 Linux 中监视完整的目录树的更改?
Posted
技术标签:
【中文标题】如何在 Linux 中监视完整的目录树的更改?【英文标题】:How to monitor a complete directory tree for changes in Linux? 【发布时间】:2012-01-31 17:26:42 【问题描述】:我如何监控整个目录树在 Linux(ext3 文件系统)中的变化?
目前该目录包含大约 50 万个文件,分布在大约 3,000 个子目录中,分为三个目录级别。
这些文件大多是小文件(
我知道有 inotify 和排序,但 AFAIK 他们只监控一个目录,这意味着我需要 3,000 个 inotify 句柄 - 比单个进程允许的通常 1024 个句柄多.还是我错了?
万一Linux系统不能告诉我我需要什么:也许有一个FUSE项目模拟文件系统(复制真实文件系统上的所有文件访问)并单独记录所有修改(一个都不好)?
【问题讨论】:
【参考方案1】:我使用inotifywait
工具做了类似的事情:
#!/bin/bash
while true; do
inotifywait -e modify,create,delete -r /path/to/your/dir && \
<some command to execute when a file event is recorded>
done
这将在整个树上设置递归目录监视,并允许您在发生变化时执行命令。如果您只想查看更改,可以添加-m
标志使其进入监控模式。
【讨论】:
要避免while loop
,请使用-m
或--monitor
开关/选项/标志/参数。不知道那个“开关”是什么时候出现的,但比循环更好
您还应该添加move
事件:inotifywait -e modify,create,delete,move -r /path/to/your/dir
这种方法不会错过一个事件,以防其中两个事件在一瞬间发生?在 inotifywait 存在之后,会有一段时间没有事件被监控,不是吗?
@gwillie,但如果使用m
标志,它只会输出到stdout
,我们无法使用该触发器执行任何命令。那么,如果你想在观察到任何事件后执行某些事情,while
循环不是更好吗?【参考方案2】:
$ inotifywait -m -r /path/to/your/directory
此命令足以递归地监视目录中的所有事件,例如访问、打开、创建、删除...
【讨论】:
是的,但是诸如访问和打开之类的事件非常有问题。取决于你的意图是什么。示例:每次 www 目录中发生更改时,我都想重新启动cordova run
。结果,cordova 生成的开放访问事件触发了 inotifywait,进入了无限循环。 -e modify,create,delete,move
更适合大多数用途。【参考方案3】:
据我所知,除了在每个目录上递归设置 inotify
监视之外别无他法。
也就是说,您不会用完文件描述符,因为inotify
不必保留 fd 来监视文件或目录(其前身 dnotify
确实受到此限制)。 inotify
改用“监视描述符”。
根据inotifywatch 的文档,默认限制是8192 个监视描述符,您可以通过将新值写入/proc/sys/fs/inotify/max_user_watches
来增加它。
【讨论】:
听起来不错。使用这么多手表描述符时需要考虑哪些负面因素? 不,除了创建所有手表所花费的时间之外,我认为您不会遇到只有 3000 个子目录的问题。 这不会造成可能的种族问题,例如:在folder_main
中创建folder_sub
,在folder_sub
中创建folder_sub_sub
,folder_main
的inotify 到达,手表设置在folder_sub
,但是folder_sub_sub
已经错过了,所以上面还没有安装手表?
Ubuntu 18.04 现在将默认值“max_user_watches”设置为 65536,这在普通桌面/服务器系统中似乎是一个合理的值。【参考方案4】:
当你有很多子目录时,inotify 是最好的选择,但如果不是,我习惯使用下面的这个命令:
watch -d find <<path>>
【讨论】:
手表是首选watch
不允许分页,因此它会丢失任何比终端高度长的东西(例如,tree
文件数 > 终端行数的命令)
我很想看到支持find
每 5-10 秒处理 50 万个文件的硬件(以及该方法对其工作负载的影响)。 ...如果我是您的系统管理员并且看到您制造这种负载,我会追捕您并与您进行非常严厉的谈话。
@tink 当然,如果您有很多文件要检查,那么多次运行find
不是可行的方法。我的回答可以帮助那些想要检查子目录但无权访问inotify
的人。正如我建议的那样,inotify
是当你有很多文件时最好的选择。【参考方案5】:
使用 inotify-tools 中的 inotifywait:
sudo apt install inotify-tools
现在创建一个包含隐藏文件和文件夹的脚本myscript.sh
:
#!/bin/bash
while true; do
inotifywait -e modify,create,delete,move -r $1
done
使用chmod +x myscript.sh
使脚本可执行
使用./myscript.sh /folder/to/monitor
运行它
如果你不提供参数,它将默认使用工作目录。
另外,您可以运行多个命令,在上一条命令末尾添加&& \
以添加下一条:
#!/bin/bash
while true; do
inotifywait -e modify,create,delete,move -r $1 && \
echo "event" && \
echo "event 2"
done
如果您不想对事件执行任何命令,只需使用 -m
修饰符直接运行命令,这样就不会关闭:
inotifywait -e modify,create,delete,move -m -r /path/to/your/dir
【讨论】:
【参考方案6】:不是 fanotify 最终应该提供这种能力吗? 引用LWN:
“fanotify 有两种基本的‘模式’定向和全局。 [...] fanotify global 反而表明 它想要系统上的所有内容,然后单独标记 它不关心的 inode。”
不过,我不知道它的最新状态是什么。
【讨论】:
根据对***.com/a/1847268/130352 的评论... fanotify 进入 2.6.36。【参考方案7】:我有一个不同的建议,仅针对文件的更改,并记录历史更改
使用 git
cd /folder_to_monitor
git init
git add *
git commit -m "first snapshot"
所以在你做出改变之后
git diff
【讨论】:
在某些情况下它可能是一个有效的选项。不值得 -1【参考方案8】:特别是对于您希望根据所见触发事件的大型或复杂监控任务,请查看Watchman A file watching service。这是一个简单的示例,用于在 CSS 文件更改时运行名为 minify-css 的工具:
$ watchman watch ~/src
$ watchman -- trigger ~/src buildme '*.css' -- minify-css
它进行全面的日志记录,可以有效地处理目录结构中重叠的多个手表,可以从命令行或通过 json 进行管理,等等。另见
Watchman – A File and Directory Watching Tool for Changes它可以通过 Debian Sid 和 Ubuntu 20.04 获得,据我所知,它几乎已经两次进入 Fedora(1450590 和 1564720)。
【讨论】:
【参考方案9】:我用它来快速浏览当前目录:
watch 'find . -printf "%T@ %Tc %p\n" | sort -nr | head '
【讨论】:
投反对票,因为 1)它没有回答问题(head
将削减绝大多数输出)和 2)考虑到 OP 的文件和目录的数量,这个答案甚至是不切实际的如果它是正确的,因为它会定期再次查看所有文件。 OP 一直在寻找更强大且开销更低的解决方案。以上是关于如何在 Linux 中监视完整的目录树的更改?的主要内容,如果未能解决你的问题,请参考以下文章