Сделать inotifywait группировать несколько файловых обновлений в один?
У меня есть папка с документами Sphinx, с которой я смотрю inotifywait
(от inotify-tools). Скрипт перестраивает html & singlehtml и обновляет Chrome.
#!/bin/sh
inotifywait -mr source --exclude _build -e close_write -e create -e delete -e move | while read file event; do
make html singlehtml
xdotool search --name Chromium key --window %@ F5
done
Это прекрасно работает, когда я сохраняю один файл. Тем не менее, когда я hg update
в старую ревизию или вставьте несколько файлов в source
папка, он запускает скрипт для каждого файла.
Есть ли простой обходной путь (без написания пользовательских сценариев Python - это я могу сделать), чтобы заставить его подождать долю секунды перед запуском сценария?
2 ответа
Я сделал немного более сложный сценарий оболочки и разместил его в статье:
inotifywait -mr source --exclude _build -e close_write -e create -e delete -e move --format '%w %e %T' --timefmt '%H%M%S' | while read file event tm; do
current=$(date +'%H%M%S')
delta=`expr $current - $tm`
if [ $delta -lt 2 -a $delta -gt -2 ] ; then
sleep 1 # sleep 1 set to let file operations end
make html singlehtml
xdotool search --name Chromium key --window %@ F5
fi
done
Это делает журнал inotifywait не только имя файла и действия, но и отметку времени. Сценарий сравнивает метку времени с текущим временем unixtime и, если дельта меньше 2 секунд, он запускается make html
, Но перед этим он спит 1 секунду, чтобы завершить операции с файлами. Для следующих измененных файлов временная метка будет старой, дельта будет более 2 секунд, и ничего не будет сделано.
Я обнаружил, что этот способ потребляет меньше всего ресурсов процессора и является наиболее надежным.
Я также попытался запустить простой скрипт на Python, но это означало, что если я вставил в папку что-то такое большое, как jQueryUI, тысячи процессов были запущены, а затем превратились в зомби.
Попробуй это:
last_update=0
inotifywait -mr source --exclude _build -e close_write -e create \
-e delete -e move --format '%T' --timefmt '%s' |
while read timestamp; do
if test $timestamp -ge $last_update; then
sleep 1
last_update=$(date +%s)
make html singlehtml
xdotool search --name Chromium key --window %@ F5
fi
done
--format '%T' --timefmt '%s'
заставляет метку времени выводиться для каждого события.test $timestamp -ge $last_update
сравнивает метку времени события с меткой времени последнего обновления. Любые события, которые произошли во время сна, таким образом, пропускаются.sleep 1
добавлено для ожидания накопления событий. Более короткая продолжительность может быть хорошей, например,sleep 0.5
, но это было бы менее переносимым.last_update=$(date +%s%N)
устанавливает метку времени последнего обновления, которое будет сравниваться с меткой времени следующего события. Таким образом, любые дополнительные события, которые происходят во времяsleep 1
отбрасываются во время следующей итерации цикла.
Обратите внимание, что здесь есть условие гонки, потому что strftime() не поддерживает наносекунды. Этот пример может работать make
дважды, если группа событий пересекает вторую границу. Чтобы вместо этого рискнуть пропустить события, заменить -ge
с -gt
,