【问题标题】:How to monitor a complete directory tree for changes in Linux?如何在 Linux 中监视完整的目录树的更改?
【发布时间】:2012-01-31 17:26:42
【问题描述】:

我如何监控整个目录树在 Linux(ext3 文件系统)中的变化?

目前该目录包含大约 50 万个文件,分布在大约 3,000 个子目录中,分为三个目录级别。

这些文件大多是小文件(

我知道有 inotify 和排序,但 AFAIK 他们只监控一个目录,这意味着我需要 3,000 个 inotify 句柄 - 比单个进程允许的通常 1024 个句柄多.还是我错了?

万一Linux系统不能告诉我我需要什么:也许有一个FUSE项目模拟文件系统(复制真实文件系统上的所有文件访问)并单独记录所有修改(一个都不好)?

【问题讨论】:

    标签: linux monitoring filesystemwatcher inotify


    【解决方案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_subfolder_main 的inotify 到达,手表设置在folder_sub ,但是folder_sub_sub已经错过了,所以上面还没有安装手表?
    • Ubuntu 18.04 现在将默认值“max_user_watches”设置为 65536,这在普通桌面/服务器系统中似乎是一个合理的值。
    【解决方案4】:

    当你有很多子目录时,inotify 是最好的选择,但如果不是,我习惯使用下面的这个命令:

    watch -d find &lt;&lt;path&gt;&gt;

    【讨论】:

    • 手表是首选
    • 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 运行它

    如果你不提供参数,它将默认使用工作目录。

    另外,您可以运行多个命令,在上一条命令末尾添加&amp;&amp; \ 以添加下一条:

    #!/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。

      不过,我不知道它的最新状态是什么。

      【讨论】:

      【解决方案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 进行管理,等等。另见

      它可以通过 Debian Sid 和 Ubuntu 20.04 获得,据我所知,它几乎已经两次进入 Fedora(14505901564720)。

      【讨论】:

        【解决方案9】:

        我用它来快速浏览当前目录:

        watch 'find . -printf "%T@ %Tc %p\n" | sort -nr | head '
        

        【讨论】:

        • 投反对票,因为 1)它没有回答问题(head 将削减绝大多数输出​​)和 2)考虑到 OP 的文件和目录的数量,这个答案甚至是不切实际的如果它是正确的,因为它会定期再次查看所有文件。 OP 一直在寻找更强大且开销更低的解决方案。
        猜你喜欢
        • 2010-10-20
        • 1970-01-01
        • 1970-01-01
        • 2011-10-10
        • 2010-12-13
        • 2011-04-28
        • 1970-01-01
        • 2011-04-11
        • 2012-01-12
        相关资源
        最近更新 更多