Jak zaktualizować bibliotekę współdzieloną bez awarii?

18

Tutaj napisano, że możesz przepisać plik wykonywalny, a proces będzie działał dobrze - zostanie ponownie odczytany po ponownym uruchomieniu procesu.

Jednak gdy próbuję zastąpić plik binarny podczas procesu (za pomocą scp, od dewelopera do serwera testowego), mówi „plik zajęty”. A jeśli zastąpię plik biblioteki współdzielonej (* .so), wszystkie procesy, które go łączą, ulegają awarii.

Dlaczego tak? Czy coś brakuje? Jak mogę zamienić pliki binarne bez zatrzymywania / zawieszania procesu?

Sam
źródło
Możesz sprawdzić .soplik za pomocą, ldd filename.soaby sprawdzić zależności
Rahul Patil
Znam zależności. Chcę sposób na zastąpienie tych plików bez wpływu na uruchomione procesy. Jak sugeruje powiązane pytanie
Sam
wymagany jest przestój .. lub możesz to zrobić stop app && create symlink of .so && start app
Rahul Patil

Odpowiedzi:

21

Jak wspomniano w Dlaczego pakiet oprogramowania działa dobrze, nawet gdy jest aktualizowany? , blokada jest umieszczona na i-węźle, a nie na nazwie pliku. Po załadowaniu i uruchomieniu pliku binarnego plik jest oznaczony jako zajęty - dlatego podczas próby zapisania pojawia się błąd ETXTBSY (plik zajęty).

Teraz w przypadku bibliotek współdzielonych jest nieco inaczej: biblioteki mapują pamięć do przestrzeni adresowej procesu za pomocą mmap(). Chociaż MAP_DENYWRITEmoże być określony, przynajmniej Glibc w systemie Linux dyskretnie go ignoruje (zgodnie ze stroną podręcznika, sprawdź źródła) - sprawdź ten wątek . W związku z tym możesz zapisać plik, a ponieważ jest on zamapowany w pamięci, wszelkie zmiany są widoczne niemal natychmiast - co oznacza, że ​​jeśli spróbujesz wystarczająco mocno, możesz udaremnić swój komputer, nadpisując bibliotekę.

Dlatego poprawnym sposobem aktualizacji jest:

  1. usunięcie pliku, który usuwa odniesienie do danych z systemu plików, dzięki czemu nie jest dostępny dla żadnych nowo powstałych aplikacji, które mogą chcieć z niego korzystać, jednocześnie zachowując dostęp do danych dla każdego, kto już go otworzył (lub zmapował) ;

  2. tworzenie nowego pliku ze zaktualizowaną zawartością.

Nowo utworzone procesy będą korzystać ze zaktualizowanej zawartości, uruchomione aplikacje będą miały dostęp do starej wersji. Tak właśnie działa każde rozsądne narzędzie do zarządzania pakietami. Pamiętaj jednak, że nie jest to całkowicie pozbawione niebezpieczeństwa - na przykład aplikacje dynamicznie ładujące kod (używające dlsym()i znajomych) będą miały problemy, jeśli API biblioteki zmieni się po cichu.

Jeśli chcesz być po naprawdę, naprawdę bezpiecznej stronie, zamknij system, zamontuj system plików z innej instancji systemu operacyjnego, zaktualizuj i ponownie uruchom zaktualizowany system.

Peter
źródło
6

Aktualizacja rpm robi to samo - z uruchomionymi plikami binarnymi i bibliotekami, gdy nic się nie zawiesza.

Jaka jest różnica:

  1. rozłącz plik
  2. napisz nowy plik o tej samej nazwie

NIE spowoduje to zastąpienia pliku w miejscu: i-węzeł odnoszący się do pliku binarnego w użyciu jest nadal „zajęty”, dopóki ostatni obiekt trzymający go nie otworzy się. Nowy plik zostanie utworzony z nowym numerem i-węzła.

Teraz scplub cpspróbuje zastąpić plik w miejscu - co zmieniłoby treść, do której odnosi się i-węzeł. To nie działa - jak opisano.

Nils
źródło