Використання inotifywait разом з vim


14

У мене є простий скрипт, який відстежує файл за змінами і rsyncs його з віддаленою копією:

#!/bin/bash

while inotifywait -e close_write somefile
do
    rsync somefile user@host.domain:./somefile
done

Він добре працює з нано, але не справляється з vim. Коли я використовую нано, він виводить:

somefile CLOSE_WRITE,CLOSE   

і починається наступний цикл, чекаючи іншого видання.

Коли я використовую vim, виходу немає, сценарій просто закривається кодом виходу 0.

Я провів деякі дослідження і виявив, що close_write є правильним параметром для uing initofywait разом з vim (спочатку я хотів використати подію модифікації), але чомусь це не вдається для мене.


Це працює для мене. Ви змінили файл у vim перед тим, як зберегти його, а не просто відкрити його для редагування?
roaima

@roaima Це працює лише в тому випадку, якщо backupcopyпараметр вимкнено.
Жиль "ТАК - перестань бути злим"

Відповіді:


15

Редактори можуть дотримуватися декількох стратегій для збереження файлу. Два основні варіанти - це перезаписати існуючий файл або записати в новий файл і перемістити його на місце. Запис у новий файл і переміщення його на місці має приємне властивість, що в будь-який момент часу читання з файлу дає вам повну версію файлу (один миттєвий старий, наступний миттєвий новий). Якщо файл перезаписаний на місці, є час, протягом якого він є неповним, що проблематично, якщо якась інша програма отримує доступ до нього саме тоді або якщо система виходить з ладу.

Нано, мабуть, перезаписує існуючий файл. Ваш сценарій визначає точку, коли він закінчується написанням ( close_writeподією) і працює rsyncв цій точці. Зауважте, що rsync може захопити неповну версію файлу, якщо ви двічі швидко зберігаєте її, перш ніж rsync виконає свою роботу з першого збереження.

Vim, з іншого боку, використовує стратегію запису-перенесення - щось для цього

echo 'new content' >somefile.new
mv -f somefile.new somefile

Що відбувається зі старою версією файлу, це те, що він видаляється в місці, коли нова версія переміщується на місце. У цей момент inotifywaitкоманда повертається, тому що файл, якому сказали дивитися, вже не існує. (Новий somefile- це інший файл з тим самим іменем.) Якби Vim був налаштований на створення резервного файлу, що трапилось би щось подібне

echo 'new content' >somefile.new
ln somefile somefile.old
mv -f somefile.new somefile

і inotifywaitзараз би спостерігав за резервною копією.

Щоб отримати додаткові відомості про стратегії збереження файлів, див. Як можливо зробити оновлення в реальному часі під час роботи програми? і дозволи на збереження файлів та збереження

Vim може бути запропоновано використовувати стратегію перезапису: вимкніть backupcopyпараметр ( :set nobackupcopy). Це ризиковано, як зазначено вище.

Щоб обробляти обидві стратегії збереження, перегляньте каталог та фільтруйте обидва close_writeта moved_toподії somefile.

inotifywait -m -e close_write,moved_to --format %e/%f . |
while IFS=/ read -r events file; do
  if [ "$file" = "somefile" ]; then
    …
  fi
done

Недолік запропонованого тут методу полягає в тому, що коли ви записуєте кілька файлів «одразу», ваші команди будуть запускатися один раз для кожного файлу. Я редагую код, тому можу змінити заголовок та пару інших перекладацьких одиниць і :wa. Тоді моя збірка запускається один раз для кожного написаного файлу.
Обмежене спокутування

@LimitedAtonement Це набагато складніший випадок використання, ніж той, що знаходиться в цьому запитанні. Для вашого випадку використання вам потрібно буде трохи почекати після збереження одного файлу. Файли ніколи не змінюються "відразу". Якщо ви збережете декілька файлів за допомогою :wa, ви отримаєте послідовні ініціативні події. Вам потрібно буде почекати після першого, щоб побачити, чи приходять інші. Але ви можете скористатися представленим тут кодом: додаткова складність полягатиме всередині .
Жиль "ТАК - перестань бути злим"

@Gilles я вирішив while true; do inotifywait ... [no -m]; make; sleep .1; done;чи так. Є якісь ґетчі, але я прийшов до чогось досить працездатного.
обмежене спокута
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.