Как я могу прервать или отменить цикл inotifywait?

У меня есть небольшой скрипт, который следит за изменениями в файлах, используя inotifywait. Когда что-то меняется, пакет файлов отправляется через процесс (компилируется, сжимается, реорганизуется и т. д.), выполнение которого занимает около десяти секунд.

Рассмотрим следующий пример:

touch oli-test
inotifywait -mq oli-test | while read EV; do sleep 5; echo "$EV"; done

Если вы запустите touch oli-test в другом терминале несколько раз, вы увидите, что каждый цикл завершается, прежде чем двигаться дальше. Этот сценарий очень реален для меня. Если я забуду сохранить файл, пока он уже обрабатывается, или замечу ошибку, события складываются, и я жду несколько минут.

Меня поражает, что есть две техники, которые объективно сделают этот рабочий процесс лучше. Я не уверен, что проще или лучше, поэтому я представляю оба:

  1. Прервать предыдущие прогоны и немедленно перезапустить. Скриптовый процесс в настоящее время представляет собой просто встроенный набор команд. Я мог бы разбить их на функции Bash, я не горю желанием разбивать их дальше.

  2. Отменить дребезг списка вещей, ожидающих обработки, чтобы, если пять событий произошли одновременно (или когда он уже обрабатывается), он запускался только один раз.

(Или оба... потому что я уверен, что есть случаи, когда оба были бы полезны)

Я также открыт для подходов, которые отличаются от inotifywait, но они должны дать мне тот же результат и работать над Ubuntu.


person Oli    schedule 28.01.2015    source источник


Ответы (2)


Чтобы прервать, вы можете переставить вещи так, чтобы обработка выполнялась в фоновой подоболочке, и каждое новое событие inotifywait сбрасывало фоновые процессы:

inotifywait -mq oli-test | while read EV; do
    jobs -p | xargs kill -9
    (
        # do expensive things here
        sleep 5  # a placeholder for compiling
        echo "$EV"
    ) &
done
person Oli    schedule 28.01.2015
comment
Это выглядит как хорошее решение для того, что вы пытаетесь сделать. - person hek2mgl; 28.01.2015

Я пишу это решение, работающее только в том случае, если установлено приложение bc (калькулятор), потому что bash не может обрабатывать числа с плавающей запятой.

lastRunTime=$(date +'%H%M%S.%N')

inotifywait -mr ./web -e create -e delete -e modify | while read file event tm; do

    currentTime=$(date +'%H%M%S.%N')
    delta=$(bc <<< "$lastRunTime - $currentTime")
    echo "$currentTime, $lastRunTime, $delta"

    if (( $(echo "$delta < -1.0" | bc -l) )); then
        echo "run"
        lastRunTime=$(date +'%H%M%S.%N')
    fi

done

Объясните: здесь мы устанавливаем дату и время последнего запуска как СЕЙЧАС, а следующий запуск разрешен только в том случае, если дата и время последнего запуска ‹ дельта (в моем случае -1,0).

Пример:

Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
120845.009293691, 120842.581019388, -2.428274303
run
120845.018643243, 120845.017585539, -.001057704
120845.026360234, 120845.017585539, -.008774695

person Hellcore    schedule 19.06.2019