2

inotifywait用来在文件系统事件发生时运行命令。我希望这等待 5 秒以查看是否发生另一个文件系统事件,如果发生另一个事件,我想将计时器重置回 5 秒并再等一会儿。说得通?

我的问题是我在 Bash 中对此进行攻击,但我不知道该怎么做。在 JavaScript 中,我将 setTimeout 与如下代码一起使用:

function doSomething() { ... }

var timer;
function setTimer() {
    window.clearTimeout(timer)
    timer = window.setTimeout(doSomething, 5000);
}

// and then I'd just plug setTimer into the inotifywait loop.

但是 Bash 中有可寻址、可清除的后台计时器吗?

4

2 回答 2

1

我一直在喋喋不休的一个想法是分叉一个子shell,它会休眠,然后运行我想要的结束命令,然后将其填充到后台。如果再次运行,它将获取先前的 PID 并尝试对其进行核对。

作为一项安全功能,在 sleep 完成后,子 shell 会清除 $PID 以避免在command执行过程中被杀死

PID=0
while inotifywait -r test/; do
    [[ $PID -gt 0 ]] && kill -9 $PID
    { sleep 5; PID=0; command; } & PID=$!
done

这有点乱,但我已经测试过它并且它有效。如果我在 ./test/ 中创建新文件,它会看到并且如果 $PID 不为零,它将终止先前的睡眠命令并重置计时器。

于 2013-08-30T11:15:22.437 回答
0

我提供这个答案是为了说明一个类似但更复杂的用例。请注意,@Oli 提供的代码包含在我的答案中。

我想在文件更改时发布处理文件。具体来说,我想在文件上调用 dart-sassscss以生成css文件及其映射文件。然后css文件被压缩。

我的问题是scss可以直接通过 vim(在写入文件时使用备份副本)或通过 SFTP(特别是使用 macOS Transmit)来编辑/保存源文件。这意味着可以将更改inotifywait视为一对或单个(由于我认为是通过 SFTP 的CREATEcmd )。因此,如果我看到 a或 a后面没有任何东西,我必须启动处理。CLOSE_WRITE,CLOSECREATERENAMECLOSE_WRITE,CLOSECREATE

评论:

  • 它必须处理多个并发编辑/保存。
  • 表格传输使用的临时文件<filename>_safe_save_<digits>.scss不得考虑。
  • 的版本inotify-tools是 3.20.2.2 并且已经从源代码编译(没有包管理器)以获得带有include选项的最新版本。
#!/usr/bin/bash

declare -A pids

# $1: full path to source file (src_file_full)
# $2: full path to target file (dst_file_full)
function launch_dart() {
  echo "dart"
  /opt/dart-sass/sass "$1" "$2" && /usr/bin/gzip -9 -f -k "$2"
}

inotifywait -e close_write,create --include "\.scss$" -mr assets/css |
grep -v -P '(?:\w+)_safe_save_(?:\d+)\.scss$' --line-buffered |
  while read dir action file; do
    src_file_full="$dir$file"
    dst_dir="${dir%assets/css/}"
    dst_file="${file%.scss}.css"
    dst_file_full="priv/static/css/${dst_dir%/}${dst_file}"

    echo "'$action' on file '$file' in directory '$dir' ('$src_file_full')"
    echo "dst_dir='$dst_dir', dst_file='$dst_file', dst_file_full='$dst_file_full'"

    # if [ "$action" == "DELETE" ]; then
    #   rm -f "$dst_file_full" "${dst_file_full}.gz" "${dst_file_full}.map"
    if [ "$action" == "CREATE" ]; then
      echo "create. file size: " $(stat -c%s "$src_file_full")
      { sleep 1; pids[$src_file_full]=0; launch_dart "$src_file_full" "$dst_file_full"; } & pids[$src_file_full]=$!
    elif [ "$action" == "CLOSE_WRITE,CLOSE" ]; then
      [[ ${pids[$src_file_full]} -gt 0 ]] && kill -9 ${pids[$src_file_full]}
      launch_dart "$src_file_full" "$dst_file_full"
    fi
  done
于 2020-09-17T11:15:24.030 回答