Na liście dyskusyjnej linux-api omówiono propozycję (RFC) zastąpienia przestarzałych binarnych formatów dzienników systemowych lastlog, btmp, utmp i wtmp nowymi, współdzielonymi bibliotekami, które wykorzystują SQLite jako backend. Inicjatywa ma na celu rozwiązanie kumulujących się problemów, w tym przepełnienia 32-bitowych liczników czasu w 2038 roku, braku elastyczności, niskiej wydajności zapytań oraz braku atomowości przy zapisie.
Obecnie w systemie Linux do przechowywania danych o sesjach i próbach uwierzytelnienia używane są następujące pliki binarne o stałej strukturze:
- /var/log/lastlog — время последнего входа (структура «struct lastlog» с полем «ll_time» 32-разрядного типа time_t);
- /var/log/btmp — неудачные попытки входа;
- /var/run/utmp — текущие сеансы;
- /var/log/wtmp — история входов и выходов.
Format danych tych plików został opracowany kilka dziesięcioleci temu i ma szereg fundamentalnych ograniczeń:
- Pole „tv_sec” w strukturze „utmpx” oraz pole „ll_time” w „lastlog” mają typ „int32_t”, a wartość liczników czasu, na podstawie którego nastąpi przepełnienie, w dniu 19 stycznia 2038 roku. Z powodu wymagań dotyczących kompatybilności ABI, nawet na 64-bitowych systemach, te pola pozostają 32-bitowe, więc problem dotknie wszystkie instalacje systemu Linux.
- Stały rozmiar wpisów nie pozwala na dodawanie nowych pól (na przykład identyfikator kontenera, nazwa usługi, adres IP) bez całkowitej wymiany formatu i rekompilacji wszystkich narzędzi.
- Narzędzia last, lastb, who i lastlog muszą liniowo przeszukiwać zawartość plików. Przy dużych rozmiarach dzienników, bez użycia indeksów, które umożliwiają efektywne filtrowanie wpisów, obciążenie systemu wejścia/wyjścia oraz opóźnienia podczas wykonywania zapytań stają się nieakceptowalne.
- Zapis do pliku binarnego nie jest operacją atomową. W przypadku awarii zapis może zostać częściowo uszkodzony.
- Aby uniknąć konfliktów przy jednoczesnym zapisie do dzienników przez wiele procesów (na przykład sshd i login), stosuje się blokady flock, które nie gwarantują atomowości i mogą prowadzić do zakleszczeń.
Autor RFC proponuje całkowite porzucenie binarnych formatów na rzecz wyspecjalizowanych bibliotek współdzielonych, wykorzystujących SQLite. Dla każdego typu dzienników tworzona jest osobna biblioteka z jednolitym interfejsem C: liblastlog2, libbtmp2, libutmp2 i libwtmp2. Wszystkie biblioteki pracują z bazą danych, której schemat zawiera 64-bitowe znaczniki czasowe (typ INTEGER) i indeksy według użytkownika i czasu. Istnieje możliwość dodawania nowych pól bez naruszania kompatybilności (za pomocą ALTER TABLE).
Wśród argumentów na rzecz użycia SQLite wspomina się o wykorzystaniu 64-bitowego typu INTEGER do przechowywania czasu epokowego, zastosowaniu indeksów w celu zmniejszenia I/O dzięki selektywnemu dostępowi do rekordów zamiast pełnego skanowania, możliwości dodawania nowych pól bez zmiany istniejących rekordów, wsparciu dla transakcji ACID, trybie WAL (Write-Ahead Logging) dla równoległego dostępu bez blokad oraz sprawdzonej niezawodności działania SQLite.
Aby zapewnić płynne przejście, proponuje się strategię „podwójnego zapisu” (dual-write):
- Programy, które zapisują do plików binarnych (login, sshd, sudo, cron itp.), zostaną zmodyfikowane w taki sposób, aby jednocześnie zapisywały dane zarówno w starym pliku binarnym, jak i w nowej bazie danych SQLite za pośrednictwem odpowiedniej biblioteki.
- Opracowywane są nowe wersje narzędzi (last2, lastb2, who2, lastlog2), które odczytują dane z baz SQLite, wykorzystując indeksy do szybkiej pracy. Stare narzędzia nadal działają z wcześniejszymi plikami.
- Po kilku latach, kiedy zdecydowana większość systemów zostanie zaktualizowana, wsparcie dla zapisu do starych formatów może zostać wyłączone, a stare narzędzia — uznane za przestarzałe.
Pytania, które należy poddać dalszej dyskusji:
- Celowość podziału na osobne biblioteki lub połączenia w jedną (na przykład libsession2).
- Wybór nazw dla bibliotek i narzędzi (zachować historyczne nazwy czy przejść do bardziej ogólnych).
- Lokalizacja plików baz danych (/var/lib/ jak dla stanu aplikacji lub /var/log/ jak dla logów).
- Mechanizm wersjonowania schematów i migracji.
- Parametry wydajności SQLite dla różnych scenariuszy (serwery, systemy wbudowane).
- Zapewnienie zapasowego backendu przechowującego logi w uproszczonym formacie binarnym dla systemów, w których SQLite może być zbyt obciążające (na przykład, urządzenia wbudowane z surowymi ograniczeniami pamięci).
Źródło: opennet.ru
