Bash中的可寻址计时器

Bash中的可寻址计时器,bash,timer,inotify,Bash,Timer,Inotify,我使用inotifywait在文件系统事件发生时运行命令。我想让它等待5秒钟,看看是否有另一个文件系统事件发生,如果有另一个文件系统事件发生,我想将计时器重置回5秒钟,然后再等待一段时间。有道理吗 我的问题是我在Bash中攻击它,我不知道我会怎么做。在JavaScript中,我会将setTimeout与以下代码结合使用: function doSomething() { ... } var timer; function setTimer() { window.clearTimeout

我使用
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中是否有可寻址、可清除的后台计时器呢?

我一直在胡思乱想的一个想法是,生成一个休眠的子shell,然后运行我想要的end命令,然后将其填充到后台。如果它再次运行,它将拾取以前的PID并尝试对其进行核爆

作为一项安全功能,在睡眠完成后,子shell清除$PID以避免
命令在执行过程中被终止

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

它有点凌乱,但我已经测试过了,它可以工作了。如果我在./test/中创建新文件,它会看到,并且如果$PID不是零,它会终止之前的sleep命令并重置计时器。

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

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

我的问题是编辑/保存
scss
源文件可以直接通过vim(写入文件时使用备份副本)或通过SFTP(特别是使用macOS传输)完成。这意味着可以通过
inotifywait
将更改视为一对
CREATE
,然后是
CLOSE\u WRITE,CLOSE
或单个
CREATE
(我认为是由于
通过SFTP重命名
cmd)。因此,如果我看到一个
CLOSE\u WRITE,CLOSE
或一个
CREATE
后面没有任何内容,我必须启动处理

备注:

  • 它必须处理多个并发编辑/保存
  • 不得将传输表单
    \u safe\u save\u.scss
    所使用的临时文件考虑在内
  • inotify tools
    的版本是3.20.2.2,它是从源代码(无软件包管理器)编译而成的,使用
    include
    选项获得最新版本
#/usr/bin/bash
声明-pids
#$1:源文件的完整路径(src_file_full)
#$2:目标文件的完整路径(dst_file_full)
函数启动_dart(){
回音“飞镖”
/opt/dart-sass/sass“$1”“$2”和&/usr/bin/gzip-9-f-k“$2”
}
inotifywait-e close\u write,create--include“\.scss$”-mr assets/css|
grep-v-P'(?:\w+)\u safe\u save\u(?::\ d+)\.scss$'--缓存行|
读取dir动作文件时;做
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“$dir”目录(“$src_file_full”)中文件“$file”上的“$action”
echo“dst_dir='$dst_dir',dst_file='$dst_file',dst_file_full='$dst_file_full'”
#如果[“$action”==“DELETE”];然后
#rm-f“$dst_file_full”“${dst_file_full}.gz”“${dst_file_full}.map”
如果[“$action”==“CREATE”];然后
echo“create.file size:$(stat-c%s“$src\u file\u full”)
{sleep 1;pids[$src_file_full]=0;启动\u dart“$src_file_full”“$dst_file_full”}&pids[$src_file_full]=$!
elif[“$action”==“关闭写入,关闭”];然后
[${pids[$src_file_full]}-gt 0]&&kill-9${pids[$src_file_full]}
启动\u dart“$src\u file\u full”“$dst\u file\u full”
fi
完成

在某些情况下,您可以使用运行
sleep
的后台进程来模拟它们。不过,我不确定你将如何在你的应用程序中使用它。我不完全清楚你想要什么。但是一个小小的改进是用
{sleep5;command}&
替换对
sh
的显式调用。