6

我有一个包含我观看的 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 脚本——我可以这样做)让它在触发脚本之前等待几分之一秒?

4

2 回答 2

10

我制作了一个更复杂的 shell 脚本并将其发布在文章中

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 这样大的东西粘贴到文件夹中,就会产生一千个进程,然后变成僵尸。

于 2012-10-09T19:31:58.683 回答
1

试试这个:

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
  1. --format '%T' --timefmt '%s'导致为每个事件输出一个时间戳。
  2. test $timestamp -ge $last_update将事件时间戳与上次更新的时间戳进行比较。因此,在睡眠期间发生的任何事件都将被跳过。
  3. sleep 1添加以等待事件累积。较短的持续时间在这里可能会很好,例如sleep 0.5,但它的便携性会降低。
  4. last_update=$(date +%s%N)设置最后一次更新的时间戳,以便与下一个事件的时间戳进行比较。sleep 1以这种方式,在循环的下一次迭代期间发生的任何附加事件都将被丢弃。

请注意,这里存在竞争条件,因为 strftime() 不支持纳秒。make如果一组事件跨越第二个边界,则此示例可能会运行两次。要冒丢失事件的风险,请替换-ge-gt.

于 2017-08-12T01:03:28.757 回答