Wie aktualisiere ich eine gemeinsam genutzte Bibliothek ohne Absturz?

18

Hier steht, dass Sie eine ausführbare Datei neu schreiben können und der Prozess gut läuft - er wird neu gelesen, wenn ein Prozess neu gestartet wird.

Wenn ich jedoch versuche, eine Binärdatei zu ersetzen, während der Prozess ausgeführt wird (mit scp vom Entwickler zum Testserver), wird "Datei belegt" angezeigt. Und wenn ich eine gemeinsam genutzte Bibliotheksdatei (* .so) ersetze, stürzen alle Prozesse, die sie verknüpfen, ab.

Warum so? Vermisse ich etwas? Wie kann ich die Binärdateien ersetzen, ohne einen Prozess anzuhalten oder zum Absturz zu bringen?

Sam
quelle
Sie können die .soDatei mit ldd filename.soüberprüfen, um Abhängigkeiten zu überprüfen
Rahul Patil
Ich kenne die Abhängigkeiten. Ich möchte eine Möglichkeit, diese Dateien zu ersetzen, ohne die laufenden Prozesse zu beeinträchtigen. Wie die verknüpfte Frage impliziert
Sam
Ausfallzeit ist erforderlich .. oder Sie können tun, wie stop app && create symlink of .so && start app
Rahul Patil

Antworten:

21

Wie in erwähnt Warum funktioniert ein Softwarepaket auch während eines Upgrades einwandfrei? Befindet sich die Sperre auf Inode, nicht auf Dateiname. Wenn Sie eine Binärdatei laden und ausführen, wird die Datei als beschäftigt markiert. Aus diesem Grund wird beim Versuch, darauf zu schreiben, der ETXTBSY-Fehler (Datei besetzt) ​​angezeigt.

Für gemeinsam genutzte Bibliotheken ist dies etwas anders: Die Bibliotheken erhalten Speicher, der in den Adressraum des Prozesses mit abgebildet wird mmap(). Obwohl MAP_DENYWRITEdies spezifiziert sein mag, ignoriert zumindest Glibc unter Linux es unbemerkt (laut Manpage können Sie die Quellen überprüfen) - überprüfen Sie diesen Thread . Daher dürfen Sie die Datei tatsächlich schreiben, und da sie im Arbeitsspeicher abgelegt ist, sind alle Änderungen fast sofort sichtbar. Wenn Sie sich also anstrengen, können Sie es schaffen, Ziegel zu bauen Ihre Maschine durch die Bibliothek zu überschreiben.

Der richtige Weg zur Aktualisierung ist daher:

  1. Entfernen der Datei, wodurch der Verweis auf die Daten aus dem Dateisystem entfernt wird, sodass für neu erstellte Anwendungen, die sie möglicherweise verwenden möchten, kein Zugriff darauf möglich ist, während die Daten für alle Personen zugänglich bleiben, die sie bereits geöffnet (oder zugeordnet) haben. ;

  2. Erstellen einer neuen Datei mit aktualisierten Inhalten.

Neu erstellte Prozesse verwenden die aktualisierten Inhalte, laufende Anwendungen greifen auf die alte Version zu. Dies ist, was jedes vernünftige Paketverwaltungsdienstprogramm tut. Beachten Sie jedoch, dass dies nicht völlig ungefährlich ist. Beispielsweise treten bei Anwendungen, die Code dynamisch laden (mithilfe von dlsym()und Freunden), Probleme auf, wenn sich die API der Bibliothek unbemerkt ändert.

Wenn Sie wirklich auf der sicheren Seite sein möchten , fahren Sie das System herunter, hängen Sie das Dateisystem von einer anderen Betriebssysteminstanz aus an, aktualisieren Sie das aktualisierte System und rufen Sie es erneut auf.

peterph
quelle
6

Ein RPM-Upgrade macht dasselbe - mit laufenden Binärdateien und Bibliotheken, während nichts abstürzt.

Was ist der Unterschied:

  1. Verknüpfung der Datei aufheben
  2. Schreiben Sie eine neue Datei mit dem gleichen Namen

Dies ersetzt NICHT die vorhandene Datei: Der Inode, der sich auf die In-Use-Binärdatei bezieht, ist immer noch "beschäftigt", bis das letzte Objekt, das es geöffnet hält, beendet ist. Die neue Datei wird mit einer neuen Inode-Nummer erstellt.

Jetzt scpoder cpversuchen Sie, die Datei an Ort und Stelle zu ersetzen - dies würde den Inhalt ändern, auf den sich der Inode bezieht. Das funktioniert nicht - wie du beschrieben hast.

Nils
quelle