如何中断或消除 inotifywait 循环?
Posted
技术标签:
【中文标题】如何中断或消除 inotifywait 循环?【英文标题】:How can I interrupt or debounce an inotifywait loop? 【发布时间】:2015-03-27 13:31:35 【问题描述】:我有一个小脚本watches files for changes using inotifywait
。当某些事情发生变化时,一批文件会通过一个大约需要十秒钟运行的过程(编译、压缩、重组等)发送。
考虑以下示例:
touch oli-test
inotifywait -mq oli-test | while read EV; do sleep 5; echo "$EV"; done
如果您在另一个终端中运行 touch oli-test
几次,您会看到每个循环在继续之前完成。那个场景对我来说非常真实。如果我忘记保存正在处理的文件,或者发现错误,事件会堆积起来,我正在等待几分钟。
令我印象深刻的是,有两种技术可以客观地使这个工作流程变得更好。我不确定什么是最简单或最好的,所以我将两者都介绍:
中断之前的运行,并立即重新启动。脚本化过程目前只是一组内联命令。我可以将它们分解为 Bash 函数,我并不热衷于将它们分解得更远。
Debounce 等待处理的事件列表,这样如果五个事件同时发生(或在它已经处理时),它只会再次运行一次。
(或者两者都...因为我确信在某些情况下两者都会有用)
我也对不同于 inotifywait
的方法持开放态度,但它们需要给我相同的结果并在 Ubuntu 上工作。
【问题讨论】:
【参考方案1】:要中断,您可以转移事物,以便处理在后台子 shell 中运行,并且每个新的 inotifywait
事件都会破坏后台进程:
inotifywait -mq oli-test | while read EV; do
jobs -p | xargs kill -9
(
# do expensive things here
sleep 5 # a placeholder for compiling
echo "$EV"
) &
done
【讨论】:
这看起来是您尝试做的一个很好的解决方案。【参考方案2】:这是一个紧凑的解决方案:
inotifywait -q -m -e modify -e create -e close_write --format "%w%f" /etc/nginx/ |\
while read -r path; do
echo $path changed
echo "Skipping $(timeout 3 cat | wc -l) further changes"
service nginx reload
done
第一个 read
等待一行数据,所以这不会占用你的 CPU。 timeout 3 cat
会读取接下来 3 秒内收到的任何进一步的更改通知。只有这样nginx
才会重新加载。
【讨论】:
【参考方案3】:我编写了这个解决方案,只有在安装了 bc(计算器)应用程序后才能工作,因为 bash 无法处理浮点数。
lastRunTime=$(date +'%H%M%S.%N')
inotifywait -mr ./web -e create -e delete -e modify | while read file event tm; do
currentTime=$(date +'%H%M%S.%N')
delta=$(bc <<< "$lastRunTime - $currentTime")
echo "$currentTime, $lastRunTime, $delta"
if (( $(echo "$delta < -1.0" | bc -l) )); then
echo "run"
lastRunTime=$(date +'%H%M%S.%N')
fi
done
说明:这里我们将上次运行日期时间设置为现在,并且仅当上次运行日期时间
例子:
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
120845.009293691, 120842.581019388, -2.428274303
run
120845.018643243, 120845.017585539, -.001057704
120845.026360234, 120845.017585539, -.008774695
【讨论】:
不错,但为什么不避免使用小数呢?以上是关于如何中断或消除 inotifywait 循环?的主要内容,如果未能解决你的问题,请参考以下文章
如何连续运行 inotifywait 并将其作为 cron 或守护进程运行?