Bash中可寻址的计时器

时间:2013-08-30 11:06:31

标签: bash timer inotify

我正在使用inotifywait在文件系统事件发生时运行命令。我希望这等待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中是否有可寻址的,可清除的背景定时器?

2 个答案:

答案 0 :(得分:0)

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

作为安全功能,在睡眠完成后,子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不为零,它将终止先前的睡眠命令并重置计时器。

答案 1 :(得分:0)

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

我想对已更改的文件进行后期处理。具体来说,我想在scss文件上调用dart-sass来生成css文件及其映射文件。然后css文件被压缩。

我的问题是,可以直接通过vim(写入文件时使用备份副本)或通过SFTP(特别是使用macOS Transmit)完成编辑/保存scss源文件。这意味着可以将inotifywait看作是一对CREATE,然后是CLOSE_WRITE,CLOSE或单个CREATE(由于通过SFTP I的RENAME cmd认为)。因此,如果看到CLOSE_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