openSUSE:Paketbau von kleinen Skript-Schnipseln
Inhaltsverzeichnis
Rezepte für kleine RPM-Skripte
RPM-Spezifikationsdateien besitzen verschiedene Abschnitte, die es den Paketen erlauben Kode bei der Installation und beim Löschen laufen zu lassen. Diese kleinen Skripte werden meistens verwendet, um das laufende System mit der Information des Paketes zu aktualisieren. Diese Seite bietet einen schnellen Überblick der RPM-Skripte und eine Anzahl gewöhnlicher Rezepte für Skripte in Paketen. Eine vollständigere Behandlung von Skripten finden Sie im Maximum RPM Buch.
Syntax
Die zugrunde liegende Syntax ist ähnlich wie %build, %install und andere Abschnitte der RPM-Spezifikationsdatei. Die Skripte unterstützen ein spezielles Kennzeichen, -p, das es den Skripten erlaubt, ein einzelnes Programm direkt aufzurufen, statt eine Shell hervorzubringen, um das Programm aufzurufen (z.B. %post -p /sbin/ldconfig).
Die Skripte nehmen ebenso ein Argument entgegen, das ihnen durch den kontrollierten RPM-Bauprozess überreicht wird. Dieses Argument, auf das via $1 zugegriffen wird, gibt die Anzahl der Pakete mit diesem Namen an, die auf dem System belassen werden, wenn die Aktion abgeschlossen wird, ausgenommen für %pretrans und %posttrans, die immer mit $1 als 0 läuft ( %pretrans und %posttrans sind verfügbar in RPM 4.4 und später). Für den gewöhnlichen Fall der Installation (install), Aktualisierung (upgrade) und Deinstallation (uninstall) haben wir:
install | upgrade | uninstall | |
---|---|---|---|
%pretrans | $1 == 0 | $1 == 0 | (N/A) |
%pre | $1 == 1 | $1 == 2 | (N/A) |
%post | $1 == 1 | $1 == 2 | (N/A) |
%preun | (N/A) | $1 == 1 | $1 == 0 |
%postun | (N/A) | $1 == 1 | $1 == 0 |
%posttrans | $1 == 0 | $1 == 0 | (N/A) |
Beachten Sie, dass diese Werte variieren können, wenn es mehrere installierte Versionen des gleichen Paketes gibt. (Das passiert mit parallel installierbaren Paketen, wie z. B. der Kernel. Es kann ebenso vorkommen, dass Fehler ein Paket beim Aktualisieren behindern, den Prozess zu vollenden.) So ist es eine gute Idee, diese Konstruktion zu verwenden:
%pre if [ "$1" -gt 1 ] ; then ... fi
...für %pre und %post Skripte statt dann zu prüfen ob es gleich 2 ist.
Ausnamsweise in wirklich besonderen Fällen (wenn überhaupt) wollen wir, dass alle Skripte mit dem Null-Austritts-Status aussteigen. Da RPM in seiner Standardkonfiguration momentan keine Shellskripte mit dem Argument -e
ausführt, ausgenommen ausdrückliche exit
Aufrufe (missbilligend mit einen nicht-Null-Argument!), bestimmt der Austrittsstatus des letzten Kommandos in einem Skript seinen Austrittsstatus. Die meisten Kommandos in den Schnippseln dieses Dokuments besitzen ein "|| :
", das an sie angehängt ist, was ein generischer Trick ist, den Null-Austrittsstatus für diese Kommandos zu erzwingen, ob sie funktionierten oder nicht. Gewöhnlich ist es das wichtigste, dieses für das letzte Kommando anzuwenden, das in einem Skript ausgeführt wird, oder ein separates Kommando hinzu zu fügen, wie ein einfaches ":
" oder "exit 0
" als letztes in einem Skript. Beachten Sie, dass es vom jeweiligen Fall abhängt. Andere Fehler-Prüf-/Vermeidungs-Massnahmen könnten besser geeignet sein. Ebenso kann man spezielle Kommandos eingeben, wenn man früher ein entsprechendes Kommando im Skript gesehen hat. Das muss eine Vorbedingung sein, um erfolgreich zu sein.
Nicht-Null-Ausstiegskode eines Skripts zerbrechen Installationen/Aktualisierungen/Löschungen, so dass keine weiteren Aktionen für das Paket in einer Transaktion durchgeführt werden können (siehe Skriptaufstellung unten). Das könnte zum Beispiel verhindern, dass eine alte Version eines Paketes während der Aktualisierung gelöscht wird. Es werden doppelte rpmdb Einträge und möglicher Weise veraltete, unbekannte Dateien im Dateisystem zurück gelassen. Es gibt einige Fälle, bei denen die Transaktionen weiter gelaufen lassen wurden, als etwas im Skript Fehl schlug. Das könnte zu einem speziell zerbrochenen Setup führen. Es ist oft auf das Paket begrenzt. Während dessen, wenn man eine Transaktion mit einigen ausgefallenen Paketen fortlaufen lässt, ist es möglich, dass weiter reichende System-Probleme auftreten könnten.
Skript Abrufreihenfolge
Die Skripte in %pre und %post werden gestartet vor und nach dem ein Paket installiert wurde. Die Skripte %preun und %postun werden gestartet bevor und nachdem ein Paket deinstalliert wurde. Die Skripte %pretrans und %posttrans werden vor und nach einer Transaktion gestartet. Bei einer Aktualisierung laufen die Skripte in folgender Reihenfolge:
- %pretrans von einem neuen Paket
- %pre von einem neuen Paket
- (Paket installieren)
- %post von einem neuen Paket
- %preun von einem alten Paket
- (löschen von einem alten Paket)
- %postun von einem alten Paket
- %posttrans von einem neuen Paket
Schnipsel
Gemeinsame Bibliotheken
Die Installation von gemeinsamen Bibliotheken erfordert das Laufen von /sbin/ldconfig, um die dynamisch verlinkten Cache-Dateien zu aktualisieren. Das kann wie folgt aufgerufen werden:
%post /sbin/ldconfig %postun /sbin/ldconfig
Es ist ebenso üblich, diese Abschnitte mit der Option -p zu deklarieren, da diese oft die einzigen Programme sind, die in einem Skript aufgerufen werden. Und dass dazu unbedingt eine Shell startet, ist überflüssig:
%post -p /sbin/ldconfig %postun -p /sbin/ldconfig
Wenn anwendbar, wird der letztere Weg empfohlen. Wenn man das so macht, werden automatisch die geeigneten Abhängigkeiten auf /sbin/ldconfig zum Paket hinzu gefügt (und dafür ist es Wert, unnötiger Weise einen Shell-Prozess im Skript zu starten).
Haben Sie im Kopf, dass Abschnitte in einer RPM-Spezifikationsdatei enden, wo der nächste Abschnitt beginnt. Das kann in einigen Fällen zu unerwarteten Fehlern führen. Zum Beispiel, wenn Sie folgende Kommentare haben:
# Der Abschnitt post: %post -p /sbin/ldconfig # Der Abschnitt postun: %postun -p /sbin/ldconfig
In diesem Fall gehört der Kommentar "# Der Abschnitt postun:" für RPM zum Abschnitt post (und der Kommentar "# Der Abschnitt post:" gehört zu dem Abschnitt vor dem post-Abschnitt). In einigen Fällen (z. B. im Bausystem für SLE11 und SLE11_SP1) führt ein solches Kommando dazu, dass ein unbeabsichtigtes Argument '0' oder '1' zum Aufruf /sbin/ldconfig hinzu gefügt wird, was es mit einem Fehler scheitern läßt, wie "/sbin/ldconfig: relativer Pfad '1' verwendet, um Cache zu bauen". Darum sind traditionell Bash-Skripte für post/postun mit einer ausdrücklichen Zeile "exit 0" am Ende wesentlich sicherer - es wird vorausgesetzt, dass solche Fehler während der Installation/Deinstallation von RPM-Paketen ignoriert werden sollten - andererseits kann ein ausdrückliches "exit 1" in diesen Skripten verwendet werden, um Paket-Installations/Deinstallations-Versagen zu erzwingen (siehe oben). Zum Beispiel:
%post /sbin/ldconfig || exit 1 do_what_is_only_nice_to_have exit 0 %postun /sbin/ldconfig [ "$1" -eq 0 ] && undo_what_was_only_nice_to_have exit 0
Benutzer und Gruppen
Das wird auf einer extra Seite diskutiert.
Service
Konventionen für Init-Skripte
Alle Richtlinien für Init-Skripte vom SysV-Stil können hier gefunden werden: openSUSE:Paketbau Init-Skripte
GConf
GConf ist ein Konfigurationssystem, dass momentan vom GNOME-Dektop verwendet wird. Programme, die es verwenden, richten Standardwerte in einer Datei namens [NAME].schemas ein, die unter %{_sysconfdir}/gconf/schemas/[NAME].schemas installiert ist. Diese Standards werden dann mit dem Dämon gconf registriert, was die Konfigurationswerte anzeigt und die Anwendungen warnt, wenn Werte an Änderungen interessiert sind. Die Schemen-Dateien unterstützen ebenso die Dokumentation darüber, was jeder Wert im Konfigurationssystem bedeutet (was angezeigt wird, wenn Sie den Datenbestand im gconf-Bearbeitungs-Programm durchsuchen).
Für den Zweck des Paketbaus müssen wir während des Baus die Schema-Installation deaktivieren und ebenso die Werte in der Datei [Name).schemas mit dem gconf-Dämon bei der Installation registrieren und sie beim Entfernen aus dem Register entfernen. Aufgrund der Anordnung der Skripte ist das ein 4-Schritte-Prozess.
Eine Deaktivierung der GConf-Installation während der Paketerstellung kann folgender Maßen durchgeführt werden:
%install export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL="1" make install DESTDIR="%buildroot" ...
Die Umgebung GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL unterdrückt die Installation des Schemas während des Baus des Paketes unterschiedlich. Eine Alternative ist für einige Pakete, ein Konfigurations-Kennzeichen weiter zu geben:
%build %configure --disable-schemas ...
Unglücklicher Weise funktioniert dieser Konfigurationsweg nur, wenn der Upstream-Paketbauer deren Makefile.am angepasst hat, um es zu handhaben. Wenn das Makefile.am nicht konfiguriert ist, wird dieser Switch gar nichts machen und Sie werden statt dessen die Umgebungsvariable verwenden müssen.
Hier ist der zweite Teil:
Requires(pre): gconf2 gnome-filesystem ... %pre if [ "$1" -gt 1 ] ; then export GCONF_CONFIG_SOURCE="$(gconftool-2 --get-default-source)" gconftool-2 --makefile-uninstall-rule \ %_sysconfdir/gconf/schemas/[NAME].schemas >/dev/null || : fi
In diesem Abschnitt installieren wir die alten Schemen, wenn wir eine Aktualisierung durchführen. Die Art wie wir das machen ist zuerst, Informationen darüber zu erhalten, wo GConf seine Werte über die Zeile gconftool-2 --get-default-source speichert. Dann deinstallieren wir das Schema aus dieser Quelle. Wenn das Paket ein Paket aktualiesieren könnte, das eine andere Bezeichnung für das Schema zu einer Zeit hat, dann kommentieren wir die Zeilen nicht, um diese ebenso zu deinstallieren.
Der nächste Abschnitt betrifft die Installation des neuen Schemas:
%post export GCONF_CONFIG_SOURCE="$(gconftool-2 --get-default-source)" gconftool-2 --makefile-install-rule \ %_sysconfdir/gconf/schemas/[NAME].schemas > /dev/null || :
Hier machen wir die gleichen Dinge wie im Abschnitt %pre, um zu aktualisieren, ausgenommen der verwendete gconftool-2 Switch ist --makefile-install-rule, um die neuen Schemen zu installieren, anstelle der Nichtinstallations-Regel, um die alten Schemen zu entfernen.
Der letzte Abschnitt handelt mit dem Löschen der Schemen bei der Paketentfernung:
%preun if [ "$1" -eq 0 ] ; then export GCONF_CONFIG_SOURCE="$(gconftool-2 --get-default-source)" gconftool-2 --makefile-uninstall-rule \ %_sysconfdir/gconf/schemas/[NAME].schemas > /dev/null || : fi
Dieses Schnipsel ist nahezu das Gleiche wie das zur Aktualisierung. Warum können wir das nicht einfach mit %pre kombinieren. Die Antwort ist die, dass wir jede alte Version der Schemen während der Aktualisierung löschen wollen. Und das hat vor der Installation der neuen Version zu erfolgen (im %post SKript). Anderenfalls löschen wir das Schema, das das aktualisierende Paket installiert. Wenn es wirklich ein Entfernen ist, dass keine andere Instanz dieses Paketes auf dem System zurück gelassen werden soll, dann müssen das Schema bereinigen, bevor wir es löschen.
Es ist eine gute Praxis, das Einklecksen in die Dateiliste zu vermeiden und ausschließlich die Dateien .schemas dort aufzulisten. Das hilft, Problemen nach einer Aktualisierung vorzubeugen. Beide, die Dateiliste und das Skript %post, müssen aktualisiert werden, wenn eine neue Datei .schemas erscheint. RPM warnt, wenn nicht alle installierten Dateien in der Dateiliste erwähnt werden. Die Dateiliste des obigen Beispiels sollte wie folgt aussehen:
%files [...] %{_sysconfdir}/gconf/schemas/epiphany.schemas %{_sysconfdir}/gconf/schemas/epiphany-lockdown.schemas
anstelle von:
%{_sysconfdir}/gconf/schemas/*.schemas
Texinfo
Das GNU_Projekt und viele andere Programme verwenden das Dateiformat Textinfo für große Teile ihrer Dokumentation. Diese Info-Dateine sind gewöhnlich unter /usr/share/info/ abgelegt. Bei der Installation oder dem Löschen eines Paketes sorgt die Installationsinformation aus dem Info-Paket für das Hinzufügen der neu installierten Dateien zum Haupt-Info-Index und ihr Entfernen bei der Deinstallation.
Requires(post): info Requires(preun): info ... %post %install_info --info-dir=%{_infodir} %{_infodir}/%{name}.info.gz %postun %install_info_delete --info-dir=%{_infodir} %{_infodir}/%{name}.info.gz
Diese beiden Skriptchen sagen der Installationsinformation, die Einträge für die Info-Seiten zur Haupt-Index-Datei bei der Installation hinzu zu fügen und sie zu entfernen zur Löschzeit.
Scrollkeeper
Einige Distributionen verwenden ein Scrollkeeper-Katalog-System, um die Übersicht über die auf dem System installierten Dokumentationen zu behalten. Es gibt keine Notwendigkeit dafür, das in openSUSE zu machen. Es werden auch keine Scrollkeeper bezogenen Makros benötigt, die in Skripten aufgerufen werden müssen.
MIME Datenbanken
Die MIME-info ist ein Standard, der von freedesktop.org definiert wurde.
Diese Funktion wird verwendet, wenn das Paket irgend eine Datei in %{_datadir}/mime
installiert und die Distribution das Paket shared-mime-info
enthält.
Einige Pakete rufen update-mime-database
während der Installation auf, die mit DESTDIR
definiert ist. Es ist ein Bug, der kann den Paketbau der aktuellen MIME-Datenbank verursachen, anstelle seiner Komponenten, auch wenn DESTDIR
gesetzt ist. Der einfachste Ausweg ist, die erzeugten Dateien am Ende des %install
-Abschnitts zu löschen. Grundsätzlich alles, außer Pakete /*.xml, sind erzeugte Dateien und müssen entfernt werden.
Verwenden Sie folgendes, wenn ein Paket eine XML-Datei in code>%{_datadir}/mime/packages</code> ablegt (ab 11.3):
Requires(post): shared-mime-info Requires(postun): shared-mime-info %post /usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || : %postun /usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || :
Beginnend mit 11.4:
Requires(post): shared-mime-info Requires(postun): shared-mime-info %post %mime_database_post %postun %mime_database_postun
MIME-Typen können mit dem Paket nautilus
getestet werden. Es genügt, das Testpaket zu installieren. Starten Sie Nautilus und schauen Sie sich die Eigenschaften einer korrespondierenden Datei an. Der installierte MIME-Typ sollte dort richtig definiert sein.
Die andere Datenbank, die aktualisiert werden muss, wenn Pakete Desktop-Dateien installieren, die MIME-Anwendungen definieren, benötigt das folgende Makro im Skript (beginnend mit 11.4):
Requires(post): desktop-file-utils Requires(postun): desktop-file-utils %post %desktop_database_post %postun %desktop_database_postun
GTK+ Icon cache
Einige Distributionen (z.B. Fedora) rufen gtk-update-icon-cache
in Ihren Skripten %post
/%postun
auf, wenn eine Anwendung Icons in eines der Unterverzeichnisse %{_datadir}/icons/
installiert (solche wie hicolor
).
Unter openSUSE wird SuSEconfig
nach der Installation eines Paketes aufgerufen. So muss nichts zur Paketdatei .spec
hinzu gefügt werden. Da SuSEconfig
nur von YaST und nicht von Zypper oder anderen installierten Werkzeugen ausgeführt wird, wird empfohlen, die folgenden Makros zu verwenden (beginnend mit 11.4):
%post %icon_theme_cache_post %postun %icon_theme_cache_postun