【问题标题】:How can I interrupt or debounce an inotifywait loop?如何中断或消除 inotifywait 循环?
【发布时间】: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 几次,您会看到每个循环在继续之前完成。那个场景对我来说非常真实。如果我忘记保存正在处理的文件,或者发现错误,事件会堆积起来,我正在等待几分钟。

令我印象深刻的是,有两种技术可以客观地使这个工作流程变得更好。我不确定什么是最简单或最好的,所以我将两者都介绍:

  1. 中断之前的运行,并立即重新启动。脚本化过程目前只是一组内联命令。我可以将它们分解为 Bash 函数,我并不热衷于将它们分解得更远。

  2. Debounce 等待处理的事件列表,这样如果五个事件同时发生(或在它已经处理时),它只会再次运行一次。

(或者两者都...因为我确信在某些情况下两者都会有用)

我也对不同于 inotifywait 的方法持开放态度,但它们需要给我相同的结果并在 Ubuntu 上工作。

【问题讨论】:

    标签: bash interrupt inotify debouncing inotifywait


    【解决方案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
      
      

      【讨论】:

      • 不错,但为什么不避免使用小数呢?
      猜你喜欢
      • 2016-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多