VIM i edycja crontabów

Posted on Sat 02 September 2006 in Tips4Unices, Tips 4 VIM

Emsi podesłał mi następującego hinta dotyczącego edycji crontabów za pomocą VIM-a.

Ustawiłem sobie jakiś czas temu w vim-ie defaultowo tryb nocompatible. Generalnie ustawia on od cholery rzeczy przydatnych i mniej przydatnych, ale za to jedną komendą.
No i po jakimś czasie zauważyłem, że przestał mi działać crontab w Slacku. Było to bardzo dziwne, bo objaw był taki, że edytujesz plik, zapisujesz i... i nic. To znaczy plik ma dalej zawartość tą co poprzednio.
Nie zwykłem sprawdzać crontaba czy działa, więc babol odkryłem dopiero po jakimś czasie. Nie muszę dodawać, że trochę job-ów się nie wykonało przez to.
Bardzo mnie to wkurwiło i zacząłem szukać. Najpierw w Google'u "slackware crontab problem" itp. ale oczywiście nic. No to się domyśliłem, że winny jest VIM... Szybki strace i już było wiadomo:
VIM w trybie nocompatible, jedną z wielu rzeczy jakie robi to tworzy backupy z ~ (tyldą) na końcu. A w zasadzie nie backupy, tylko przy otwarciu robi rename(2) pliku oryginalnego na ten z tyldą i potem pisze już do nowego.
Wszystko fajnie, bo robiąc w ten sposób nie da się stracić oryginalnej wersji pliku nawet jak się miejsce skończy (rename() to nie przeszkadza), tyle że to nie dziala z crontabem!
crontab otwiera plik o określonej nazwie (np. crontab.56432), zapewnia mu właściwe uprawnienia i ownera, a następnie woła vi-a (czy inny EDITOR) do edycji. Po powrocie z edytora kasuje plik - wcześniej miał go otwartego, więc cały czas trzyma deskryptor i z tego deskryptora czyta... Tyle że, to deskryptor do starego pliku, bo VIM zrobił rename() i zapisał treść do nowego....
ARRGH!!!

O tyle wkurwiające, że oczywiście żadnych errorów tylko po cichutku kupa...

Oczywiście VIM nie jest głupi, tylko ja. Do pomocy można wykorzystać autokomendy, któych do tej pory używałem do ustawiania odpowiedniego indentowania kodu. Wystarczy dodać (za :set nocompatible!) autokomendę:

autocmd BufRead,BufNewFile crontab.*  set compatible

i po ptokach...

Morał: bądź czujny Luke!

vim