Search code examples
bashtimerinotify

Addressable timers in Bash


I am using inotifywait to run a command when a filesystem event happens. I would like this to wait for 5 seconds to see if another filesystem event happens and if another one does, I would like to reset the timer back to five seconds and wait some more. Make sense?

My problem is I'm attacking this in Bash and I don't know how I would do this. In JavaScript, I'd use setTimeout with some code like this:

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.

But are there addressable, clearable background timers in Bash?


Solution

  • One idea I've had rattling around is forking out a subshell that sleeps and then runs my desired end command, and then stuffing that in the background. If it's run again, it'll pick up the previous PID and try to nuke it.

    As a safety feature, after the sleep has finished, the subshell clears $PID to avoid the command being killed mid-execution

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

    It's a bit messy but I've tested it and it works. If I create new files in ./test/ it sees that and if $PID isn't zero, it'll kill the previous sleeping command and reset the timer.