openSUSE:Paketbau von kleinen Skript-Schnipseln

Wechseln zu: Navigation, Suche

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:

  1.  %pretrans von einem neuen Paket
  2.  %pre von einem neuen Paket
  3. (Paket installieren)
  4.  %post von einem neuen Paket
  5.  %preun von einem alten Paket
  6. (löschen von einem alten Paket)
  7.  %postun von einem alten Paket
  8.  %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