用于监视新文件目录的 bash 脚本

Posted

技术标签:

【中文标题】用于监视新文件目录的 bash 脚本【英文标题】:bash script which watches directory for new files 【发布时间】:2016-05-13 05:51:51 【问题描述】:

重要的是要立即注意“监视目录的脚本”有很多变体,我意识到 inotify-tools 将是理想的,但是这个特定的脚本被用于监视 vboxsf 文件系统,不幸的是它不转发文件系统通知。这个脚本是用来刷新文件的,所以一个单独的运行守护进程会注意到它。

下面的脚本是一个折衷方案。我花了很长时间处理各种问题

    正确的find args find 路径和 触摸找到的文件的时间。

目标是识别新文件,触摸它,以便单独运行的守护进程注意到它并随后处理它。问题是,它吞噬了 cpu 并且可能是从发现中获取的。我希望帮助找到一种更有效的方法来做到这一点。

虽然没有必要,但要进行全面测试,需要一个挂载的 vboxsf 文件系统,并像这样运行 inotifywait inotifywait -m /watches/watchdir -e attrib

在文件以某种方式刷新之前,主机端的文件创建不会导致客户机端的 ATTRIB 通知——在这种情况下,此 hack 使用“touch

thedir=/watches/watchdir

touch_me() 
    if [ "$newbie" ]; then
 #  echo "got this: $newbie"
    touch -d '-120 seconds' "$newbie"
    fi


while true
do
    newbie=`find $thedir/* -type f -mmin 0.1 2>/dev/null`
    touch_me
done

【问题讨论】:

您希望如何立即收到有关现在文件添加到目录的通知? 您没有描述创建新文件的内容。特别是,您能否在其中插入一些新的操作/命令? 我的答案已经更新,你能看看吗?你怎么看? 好像Guard is a viable solution对于共享文件夹:polling for network drives and VM shared dirs (which don't support inotify) 感谢 Guard 的提示 在尝试将它安装在 CentOS7 上遇到各种 ruby​​ 问题后,它看起来正是我所需要的但是不知道如何快速解决。没时间了。 【参考方案1】:

sysdig 之类的工具可能会有所帮助。 例如,以下命令显示在 /tmp 中打开的每个文件:

sysdig evt.type=open and fd.name contains /tmp

此工具非常复杂但功能强大,通过阅读其手册,您可能会找到解决问题的有效方法。

【讨论】:

OP 的问题不是捕获事件,而是在主机和客户机之间传播它们。【参考方案2】:

循环持续运行,无需这样做

find $thedir/* -type f -mmin 0.1

会发现文件在 6 秒前不再更改(未来不超过 55 秒,但不太可能自然发生)。 假设 find 在不到一秒的时间内运行(除非您有数千个文件),您可能希望在循环中插入 sleep 5。 另一件事是,为什么您将发现的最近更改的文件的时间倒退 2 分钟……当然,任何 2 分钟未更改的文件都处于相同的状态。 用一个很少使用的属性(如“no dump”)标记文件不是更好的选择,这样其他恶魔就不会无意中看到看起来被脚本触及但没有被触及的文件?

然后使用 find 进行密集循环,是否可以选择执行这样的操作(将 touch_me 留到 -2min 以供其他守护程序检测):

touch_me() 
  #  echo "got this: $1"
  touch -d '-120 seconds' $1


touch /tmp/file.ref
while true
do
  for FILE in $thedir/*
  do
    [ $FILE -nt /tmp/file.ref ] && touch_me $FILE
  done
  touch /tmp/file.ref
  sleep 60
done

这样,while 的每次迭代都将查找在上一次迭代之后已修改的文件。

【讨论】:

这是一个好主意,但使问题具有挑战性的是,我希望在文件创建时几乎立即进行处理。 6 秒是可以接受的,但超过 10 秒是不希望的。如果 touch 和 -nt 可以在 60 秒内使用,这可能会起作用,但不幸的是他们正在测试 >60。 好的,然后将 sleep 60 替换为 sleep 6 并执行 chattr 操作而不是 -2 分钟...您应该没问题...可能希望守护程序将属性恢复正常以停止它不会再次分开文件。【参考方案3】:

我相信主机端的文件系统类型不是vboxsf

因此,inotify-tools 可以在主机服务器端使用,对吧?

假设从主机服务器端新创建的文件上的touch 无效,对吗?

当在主机服务器端创建新文件时,inotify-tools 可以使用VBoXManage 向来宾执行touch 命令,例如:

$ VBoxManage guestcontrol execute vmname /usr/bin/touch --username root --password 'changeme' --arguments "-d '-120 seconds' /watches/watchdir/$newbie"

你怎么看?

否则你的脚本没问题,但它正在使用轮询。 因此,在这种情况下,sleep 可能是强制性的,可能会错过一些新创建的文件...

【讨论】:

这是最适合我的。我已将解决方案更改为以下内容:theuser=transmission thepass="thepassword" /usr/bin/inotifywait -q -m $thedir -e create -e moved_to | while read path action file; do # echo "The file '$file' appeared in directory '$path' via '$action'" # echo "How about: $path$file" /usr/bin/VBoxManage guestcontrol $thevm run --exe /usr/bin/touch --username root --password $thepass -- -c "$path$file" done 超级!在我这边,你让我发现了inotify-tools;谢谢!你介意接受这个答案作为最佳答案吗?

以上是关于用于监视新文件目录的 bash 脚本的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 bash 监视目录中新创建的文件?

用于搜索目录并将文件移动到新目录、删除任何副本的 Bash 脚本

如何在不使用 inotifywait 的情况下监视目录的文件更改?

linux - 监视目录中的新文件,然后运行脚本

inotify 和 bash

用于测试给定用户是不是可以读取目录和其中所有文件的 Bash 脚本?