使 inotifywait 将多个文件更新组合为一个?
Posted
技术标签:
【中文标题】使 inotifywait 将多个文件更新组合为一个?【英文标题】:Make inotifywait group multiple file updates into one? 【发布时间】:2012-08-13 08:17:01 【问题描述】:我有一个包含 Sphinx 文档的文件夹,我使用 inotifywait
(来自 inotify-tools)观看。该脚本重新构建 html 和 singlehtml 并刷新 Chrome。
#!/bin/sh
inotifywait -mr source --exclude _build -e close_write -e create -e delete -e move | while read file event; do
make html singlehtml
xdotool search --name Chromium key --window %@ F5
done
当我保存单个文件时,这很好用。但是,当我 hg update
到旧版本或将多个文件粘贴到 source
文件夹中时,它会为每个文件触发脚本。
是否有一个简单的解决方法(无需编写自定义 python 脚本——我可以这样做)让它在触发脚本之前等待几分之一秒?
【问题讨论】:
另见:unix.stackexchange.com/q/390914/26227 【参考方案1】:我做了一个稍微复杂一点的shell脚本,贴在the article:
inotifywait -mr source --exclude _build -e close_write -e create -e delete -e move --format '%w %e %T' --timefmt '%H%M%S' | while read file event tm; do
current=$(date +'%H%M%S')
delta=`expr $current - $tm`
if [ $delta -lt 2 -a $delta -gt -2 ] ; then
sleep 1 # sleep 1 set to let file operations end
make html singlehtml
xdotool search --name Chromium key --window %@ F5
fi
done
它使inotifywait
不仅记录文件名和操作,还记录时间戳。该脚本将时间戳与当前 unixtime 进行比较,如果 delta 小于 2 秒,它将运行 make html
。但在此之前,它会休眠 1 秒以结束文件操作。对于下一个修改的文件,时间戳将是旧的,增量将超过 2 秒,并且不会执行任何操作。
我发现这种方式 CPU 消耗最少且最可靠。
我也尝试运行一个简单的 Python 脚本,但这意味着如果我将 jQueryUI 这样大的东西粘贴到文件夹中,就会产生一千个进程,然后变成僵尸。
【讨论】:
【参考方案2】:试试这个:
last_update=0
inotifywait -mr source --exclude _build -e close_write -e create \
-e delete -e move --format '%T' --timefmt '%s' |
while read timestamp; do
if test $timestamp -ge $last_update; then
sleep 1
last_update=$(date +%s)
make html singlehtml
xdotool search --name Chromium key --window %@ F5
fi
done
--format '%T' --timefmt '%s'
会为每个事件输出一个时间戳。
test $timestamp -ge $last_update
将事件时间戳与上次更新的时间戳进行比较。因此,睡眠期间发生的任何事件都会被跳过。
添加sleep 1
以等待事件累积。较短的持续时间在这里可能会很好,例如 sleep 0.5
,但它的可移植性较差。
last_update=$(date +%s%N)
设置上次更新的时间戳,以便与下一个事件的时间戳进行比较。这样,sleep 1
期间发生的任何其他事件都会在循环的下一次迭代中被丢弃。
注意,这里存在竞争条件,因为 strftime() 不支持纳秒。如果一组事件跨越第二个边界,则此示例可能会运行两次make
。要冒丢失事件的风险,请将-ge
替换为-gt
。
【讨论】:
我认为last_update
没有为后续事件设置。我尝试了类似的东西,但没有奏效。我建议最好选择接受的答案
last_update
变量不是为每个事件设置的,而是为每次执行“更新”命令设置的。然后将last_update
值与每个后续事件时间戳进行比较,以确定是否需要另一个“更新”命令。我试图在上面澄清这一点。
我还把sleep 1
移到了应该在的if
语句中,以防止每个事件都发生睡眠。以上是关于使 inotifywait 将多个文件更新组合为一个?的主要内容,如果未能解决你的问题,请参考以下文章