Mam prosty skrypt, który monitoruje plik pod kątem zmian i rsynchronizuje go za pomocą zdalnej kopii:
#!/bin/bash
while inotifywait -e close_write somefile
do
rsync somefile [email protected]:./somefile
done
Działa dobrze z nano, ale nie działa z vimem. Kiedy używam nano, wyświetla:
somefile CLOSE_WRITE,CLOSE
i rozpoczyna następną pętlę, czekając na kolejną edycję.
Kiedy używam vima, nie ma danych wyjściowych, skrypt po prostu zamyka się kodem wyjścia 0.
Zrobiłem trochę badań i odkryłem, że close_write jest właściwym parametrem do korzystania z initofywait wraz z vimem (najpierw chciałem użyć zdarzenia modyfikacji), ale z jakiegoś powodu mi się nie udaje.
backupcopy
opcja jest wyłączona.Odpowiedzi:
Redaktorzy mogą stosować kilka strategii zapisywania pliku. Dwa główne warianty to zastąpienie istniejącego pliku lub zapisanie nowego pliku i przeniesienie go na miejsce. Zapisywanie do nowego pliku i przenoszenie go na miejsce ma przyjemną właściwość, która w dowolnym momencie czytania z pliku daje pełną wersję pliku (jedna chwila stara, druga chwila nowa). Jeśli plik zostanie nadpisany w miejscu, istnieje czas, w którym jest niekompletny, co jest problematyczne, jeśli jakiś inny program uzyskuje do niego dostęp właśnie wtedy lub gdy system ulega awarii.
Nano najwyraźniej nadpisuje istniejący plik. Twój skrypt wykrywa moment, w którym kończy pisanie (
close_write
zdarzenie) i uruchamia sięrsync
w tym momencie. Zauważ, że rsync może pobrać niepełną wersję pliku, jeśli zapiszesz dwa razy z rzędu, zanim rsync zakończy swoje zadanie od pierwszego zapisu.Z drugiej strony Vim stosuje strategię zapisu i przeniesienia - coś z tego wynika
Stara wersja pliku zdarza się, że zostaje on usunięty w miejscu, w którym nowa wersja jest przenoszona na miejsce. W tym momencie
inotifywait
polecenie powraca, ponieważ plik, który kazano obejrzeć, już nie istnieje. (Nowysomefile
to inny plik o tej samej nazwie.) Gdyby Vim został skonfigurowany do tworzenia pliku kopii zapasowej, to co by się stało, to coś w rodzajui
inotifywait
będzie teraz oglądać kopię zapasową.Aby uzyskać więcej informacji na temat strategii zapisywania plików, zobacz Jak można wykonać aktualizację na żywo podczas działania programu? oraz Uprawnienia do plików i zapisywanie
Vimowi można polecić użycie strategii zastępowania: wyłącz
backupcopy
opcję (:set nobackupcopy
). Jest to ryzykowne, jak wskazano powyżej.Aby obsłużyć obie strategie zapisu, obejrzyj katalog i filtruj zarówno zdarzenia, jak
close_write
imoved_to
zdarzeniasomefile
.źródło
:wa
. Następnie moja kompilacja jest uruchamiana raz dla każdego zapisanego pliku.:wa
, otrzymasz kolejne zdarzenia inotify. Musisz poczekać po pierwszym, aby zobaczyć, czy nadchodzą inni. Ale możesz użyć kodu przedstawionego tutaj: dodatkowa złożoność przejdzie do wewnątrz…
.while true; do inotifywait ... [no -m]; make; sleep .1; done;
mniej więcej tak. Jest kilka problemów, ale doszedłem do czegoś całkiem wykonalnego.