17.3 RPM
Um unter Linux auch nicht erfahrenen Anwendern Programme zur Verfügung zu stellen, hat Red Hat ein Paketsystem namens RPM (kurz für Red Hat Package Manager) eingeführt. Zuvor (und zum Teil auch immer noch) wurden Programme oder Sources meistens als ein Tar-Ball zur Verfügung gestellt. Dabei entstanden u. a. Probleme wie das Entfernen und Aktualisieren von Software oder wenn Anwendungen bestimmte Bibliotheken benötigten.
Mit RPM wurde ein Paketsystem eingeführt, das komfortabel das Installieren, Löschen und Aktualisieren von Paketen (sowohl von Binär- als auch Quellpaketen) erlaubt, ohne dass hierbei Probleme entstehen wie die mit einem anderen bekannten Betriebssystem, das bei der Deinstallation Reste der Software übrig bleiben. Bei Quellpaketen können dabei zur Installation auch eine Neuübersetzung und weitere Aktionen ausgeführt werden.
Einführung in RPM
Wer bereits Erfahrung mit RPM hat, kann diesen Abschnitt überspringen. Es wird dabei auf das Kommandozeilentool RPM eingegangen und nicht auf eines der vielen grafischen Frontends. Für mehr Details, hier speziell für mehr Optionen, sei die Manual Page zu RPM oder die Webseite von Red Hat zu RPM empfohlen. Die Einführung geht nur kurz auf die Hauptanwendungen von RPM ein.
Installieren – rpm -i
Um ein Paket zu installieren, das in einer Paketdatei abgelegt ist, müssen Sie in der Kommandozeile die Option -i und den Paketdateinamen angeben:
$ rpm -i {optionen} {paketdatei}
Weitere gängige Optionen, die Sie noch zusätzlich verwenden könnten, wären hierbei das Flag -hv, das einen Fortschrittszustand der Installation anzeigt, und das Flag --force, das die Installation erzwingt. Es gibt natürlich noch eine Menge Optionen mehr, aber diese stehen hier nicht zur Diskussion. Somit sähe eine Installation eines Paketes namens mytest-1.0.1.i386.rpm wie folgt aus:
# rpm -i mytest-1.0.1.i386.rpm
Es spricht übrigens auch nichts dagegen, sofern eine Verbindung zu einem Netzwerk (z. B. Internet) besteht, die Installation folgendermaßen auszuführen:
# rpm -i ftp://ftp.pronix.de/mypackages/mytest-1.0.1.i386.rpm
Dies empfiehlt sich allerdings bei Dialup weniger, sollte nämlich mytest.rpm noch unerfüllte Abhängigkeiten haben, so wird die Datei nicht lokal gespeichert, was hieße, dass noch einmal mytest.rpm heruntergeladen werden müsste!
Deinstallieren – rpm -e
Um ein Paket wieder vom System zu entfernen, wird das Flag -e (für erase) verwendet:
# rpm -e {option} {paketname}
Wenn Sie beim Löschen eines Pakets unsicher sind, können Sie auch die Option --test verwenden, um zu sehen, was -e als Nächstes tun würde.
Aktualisieren – rpm -U
Wollen Sie ein Paket erneuern, können Sie das Flag -U (für Upgrade) verwenden. Damit werden eventuell als »alt« markierte Pakete gelöscht (z. B. bei der Zusammenlegung von zwei Paketen) und neue installiert.
# rpm -U {option} {paketname}
Auch hierbei werden Sie das eine oder andere Mal nicht um die Option --force zum Erzwingen des Upgrades herumkommen.
Scherzhafterweise steht im Buch Maximum RPM für »U« die Erklärung »Uh, do the right thing« (Äh, mach das Richtige), was man -U auch wirklich zuschreiben kann, denn sollte ein Paket noch nicht im System existieren, so wird es installiert.
Freshen – rpm -F
Wer ein ganzes Verzeichnis mit Upgrade-Paketen besitzt, kann rpm -F auf diese anwenden, um nur neue Pakete einzuspielen, da rpm -U z. B. mit einer Fehlermeldung wie »package aaa_base-9.1–0 is already installed« abbrechen kann.
Weiteres
Des Weiteren gibt es noch eine Menge Optionen mehr für RPM, etwa zum Ermitteln von Informationen eines Paketes oder zum Überprüfen bereits installierter oder noch nicht installierter Pakete.
Benötigte Komponenten für ein einfaches RPM
Wenn Sie selbst ein eigenes Paket Ihrer Software zur Verfügung stellen wollen, benötigen Sie im Grunde drei Komponenten:
|
Die originalen Quelldateien (Sourcecode) (sog. Pristine Sources) – Diese werden gewöhnlich als TAR-Archiv zur Verfügung gestellt. Wozu die Originalquellen?, werden Sie sich fragen. Wenn Sie wollen, dass die Software auf anderen Systemen wie BSD oder Solaris laufen soll, wäre das z. B. ein Argument. Auch wenn Sie selbst nicht auf einem solchen System arbeiten, findet sich je nach Software nicht selten jemand, der den Quellcode mit ein paar Änderungen für ein entsprechendes System anpassen kann. Trotzdem sollten die originalen Quellen im TAR-Archiv niemals verändert werden! Für Zwecke der Portabilität stehen Patches zur Verfügung – die nächste Komponente. |
|
Patches – Patches werden benötigt, um Fehler zu beheben oder Anpassungen für eine bestimmte Plattform vorzunehmen. Damit bleiben die originalen Quelldateien immer unangetastet. Ein weiterer Vorteil ist, dass Patches meist auf die nächste Version übertragen werden können, während eine Änderung am Quellbaum immer per Hand in den nächsten übertragen werden müsste. |
|
Eine Informationsdatei, die den kompletten Übersetzungs-/Installationsprozess beschreibt (sog. Specfile) – Diese Datei wird benötigt, um RPM mit sämtlichen Informationen zu versorgen, die nötig sind, um daraus ein Paket zu erstellen. Diese Datei wird Spec-Datei genannt und hat eine ähnliche Funktion wie das Makefile. |
17.3.1 Verzeichnisse, die RPM benötigt
Um die Quellen in ein Verzeichnis zu stellen, verwendet RPM fünf Verzeichnisse. Hier ein Überblick der Verzeichnisse unter SUSE-Linux, die je nach Distribution auch in einem anderen Ort liegen können (bei Red Hat z. B. /usr/src/redhat):
$ ls -l /usr/src/packages
insgesamt 0
drwxrwxrwt 2 root root 48 2003–03–13 23:16 BUILD
drwxrwxrwt 8 root root 192 2003–06–06 11:03 RPMS
drwxrwxrwt 2 root root 48 2003–03–13 23:16 SOURCES
drwxrwxrwt 2 root root 48 2003–03–13 23:16 SPECS
drwxrwxrwt 2 root root 48 2003–03–13 23:16 SRPMS
Hier finden Sie im Verzeichnis /usr/src/packages folgende fünf Verzeichnisse und deren Bedeutung:
Tabelle 17.3
Verzeichnisse, die rpm verwendet
Verzeichnis
|
Bedeutung
|
/usr/src/packages/BUILD
|
Ein Arbeitsverzeichnis, wo die Quellen ausgepackt und übersetzt werden (für das Verzeichnis stellt RPM folgende Shellvariable zur Verfügung: RPM_BUILD_DIR).
|
/usr/src/packages/RPMS
|
Hier befinden sich die fertig gestellten Binärpakete.
|
/usr/src/packages/SOURCES
|
Darin werden alle Quelldateien und Patches abgelegt (für das Verzeichnis stellt RPM folgende Shellvariable zur Verfügung: RPM_SOURCE_DIR).
|
/usr/src/packages/SPECS
|
Verzeichnis für die Spec-Dateien
|
/usr/src/packages/SRPMS
|
Hier werden die erstellten Source-Pakete abgelegt.
|
17.3.2 Ein eigenes RPM-Paket erstellen
Auf den folgenden Seiten soll jetzt aus einem einfachen Listing ein eigenes Paket erstellt werden. Da Ihr erstes Paket noch keine Patches beinhaltet, soll Ihnen dieser Vorgang anhand der Sources und der Spec-Datei gezeigt werden.
17.3.3 Sources
Als Quellcode für das RPM-Paket verwenden Sie am einfachsten die Sources, die Sie schon beim Makefile verwendet haben – also main.c, test1.c, test2.c und das Makefile. Da hier als Projektname mein_projekt verwendet wurde, müssen Sie das Makefile geringfügig verändern. Daher hier nochmals das komplette Makefile:
CC = gcc
OBJECTS = main.o test1.o test2.o
LIBS = -lm
CFLAGS = -c -O
mein_projekt: $(OBJECTS)
$(CC) -o $@ $(OBJECTS) $(LIBS)
%.o: %.c
$(CC) $(CFLAGS) $<
clean:
rm *.o mein_projekt
Alle Dateien sollten sich in einem Verzeichnis befinden, woraus Sie jetzt ein komprimiertes TAR-Archiv mit den Quellen für das Projekt mein_projekt erstellen. Wichtig ist dabei, dass der Name des Verzeichnisses mit den Quellen identisch mit dem Namen des Paketes und der Versionsnummer sein sollte. Im Beispiel sei der Verzeichnisname mein_projekt-0.1.
$ ls -l mein_projekt-0.1
insgesamt 16
-rw-r--r-- 1 tot users 307 2004–04–10 12:57 Makefile
-rw-r--r-- 1 tot users 112 2004–04–07 23:36 main.c
-rw-r--r-- 1 tot users 37 2004–04–10 12:57 test1.c
-rw-r--r-- 1 tot users 38 2004–04–10 12:59 test2.c
Hierzu der Vorgang, wie Sie das Verzeichnis mein_projekt-0.1 zu einem TAR-Ball zusammenpacken und in das Verzeichnis /usr/src/packages/SOURCES verschieben:
$ tar -cvjf /usr/src/packages/SOURCES/mein_projekt-0.1.tbz2 \
mein_projekt-0.1
mein_projekt-0.1/
mein_projekt-0.1/Makefile
mein_projekt-0.1/test1.c
mein_projekt-0.1/test2.c
mein_projekt-0.1/main.c
17.3.4 Die Spec-Datei
Etwas umfangreicher gestaltet sich die Erstellung der Spec-Datei. Diesen Vorgang werde ich Ihnen anhand des Projektes mein_projekt-0.1 demonstrieren.
Die Präambel – Informationen zum Paket
Zunächst benötigen Sie die Präambel der Spec-Datei. Dabei handelt es sich um eine Datei mit den verschiedensten Informationen, die Ihnen anschließend in einer Tabelle erläutert werden. Diese Datei wird in das Verzeichnis SPECS mit der Dateiendung *.spec abgelegt. In diesem Beispiel sei der Name der Datei mein_projekt-0.1.spec.
Die Eintragung in dieser Präambel besitzt folgende Syntax:
[Schlüsselwort] : [Wert, Beschreibung]
Einige Schlüsselwörter (die Ihnen in der folgenden Tabelle gezeigt werden) müssen vorhanden sein – wobei die Reihenfolge nicht vorgegeben ist. Die entsprechenden Informationen zum Schlüsselwort sollten abgesehen von %description niemals länger als eine Zeile sein.
Tabelle 17.4
Schlüsselwörter zur Eintragung in die Präambel
Schlüsselwort
|
Muss vorhanden sein
|
Bedeutung
|
Summary
|
ja
|
Kurzbeschreibung des Paketes
|
Name
|
ja
|
Name des Programms – dieser Eintrag wird beim Label des Pakets und im Paketdateinamen verwendet.
|
Version
|
ja
|
Die Versionsnummer des Pakets – dieser Eintrag wird beim Label des Pakets und dem Paketdateinamen verwendet.
|
Release
|
ja
|
Damit geben Sie an, wie häufig das Programm in der aktuellen Form als RPM-Paket verpackt wurde (oder kurz: die Versionsnummer der Specfile).
|
Copyright
|
ja
|
Art der Lizenz, unter der das Paket verbreitet wird/werden darf (z. B. (L)GPL, Artistic, BSD, MIT etc.).
|
Group
|
ja
|
Hier lässt sich die Software in eine bestimmte Kategorie einordnen (Grafik, Editor, Spiel ...).
|
Source
|
nein
|
Der Name (oder auch die URL) der Quelldatei, von wo diese bezogen wurde
|
URL
|
nein
|
Wo sind weitere Informationen zu dieser Software zu finden, z. B. Homepage des Projektes?
|
Distribution
|
nein
|
Für welche Distribution ist das Paket ausgelegt? Geben Sie sie hier an (SUSE x.x, Red Hat x.x ...).
|
Vendor
|
nein
|
Name der Firma oder des Urhebers, der dieses Softwarepaket vertreibt
|
Packager
|
nein
|
Name/E-Mail-Adresse der Firma oder des Urhebers, der das Paket erstellt hat und das Paket weiterhin unterstützt
|
%description
|
nein
|
Diese Zeile kann mehr als eine Zeile Text haben und beschreibt das Paket bzw. die Software. %description ist schon der nächste Abschnitt und gehört eigentlich nicht mehr zur Präambel. Außerdem verwendet es nicht die o. g. Doppelpunkt-Syntax.
|
Für unser Beispiel sieht der Präambel-Abschnitt wie folgt aus:
# Dies ist eine einfache Spec-Datei für ein einfaches Testprojekt
Summary: Ein Testprojekt zum Packen einer eigenen RPM
Name: mein_projekt
Version: 0.1
Release: 1
Copyright: GPL
Group: misc/mein_projekt
Source: ftp://ftp.pronix.de/mein_projekt/mein_projekt-0.1.tbz2
URL: http://pronix.de/mein_projekt/
Distribution: SUSE Linux 9.0
Vendor: Pronix Industries
Packager: Jürgen Wolf <pronix@pronix.de>
%description
Bei diesem Paket handelt es sich um ein simples Beispiel,
um Ihnen das Erstellen eigener RPM-Pakete naeher zu erlaeutern.
Der Prep-Abschnitt – Pakete zum Erstellen vorbereiten
Mit dem Prep-Abschnitt der Spec-Datei werden die Vorbereitungen getroffen, die nötig sind, um ein Paket zu erstellen. Meistens handelt es sich dabei um das Entpacken der Quellen aus den TAR-Archiven und ggf. der Patches. Sie können diese Aufgaben entweder von einem Shellskript erledigen lassen oder aber, was meistens der Fall ist, Sie verwenden das Makro %setup, das sämtliche Arbeiten vom Auspacken bis zum Löschen eventuell durchgeführter Builds übernimmt. Der Prep-Abschnitt wird immer mit %prep eingeleitet.
%prep
%setup
Dem Makro %setup können außerdem auch noch extra einige Parameter übergeben werden – was allerdings in unserem Fall nicht nötig ist. Das Makro %setup führt gewöhnlich folgende zwei Shellbefehle aus (die Sie alternativ für %setup verwenden könnten):
rm -Rf $RPM_BUILD_DIR/mein_projekt-0.1
tar -xvjf $RPM_SOURCE_DIR/mein_projekt-0.1.tbz2
Der Build-Abschnitt – Quellen übersetzen
Nach dem Vorbereiten mit %prep folgt der Abschnitt zum Übersetzen der Quellen. Hierfür können Sie wiederum Shellskripte verwenden; wobei sich dieser Abschnitt meistens mit einem einfachen Aufruf des Makefiles begnügt – sofern Sie natürlich ein entsprechendes Makefile erstellt haben. Der Build-Abschnitt wird mit %build eingeleitet. In unserem Projekt sieht der Build-Abschnitt wie folgt aus:
%build
make
Der Install-Abschnitt
In diesem Abschnitt wird, wie man am Namen schon herauslesen kann, festgelegt, was gemacht wird, um die Software systemweit auf dem Rechner zu integrieren. Auch in diesem Fall kann man ein Shellskript verwenden, sofern man nicht auch hier im Makefile ein entsprechendes Ziel angegeben hat. Eingeleitet wird der Install-Abschnitt mit %install. Im Beispiel wird auch hierfür das Makefile mit dem Ziel install verwendet.
%install
cp "$RPM_BUILD_DIR"/mein_projekt-0.1/mein_projekt /usr/bin
Das Ganze müsste allerdings in ein Sub-Root (eine Art chroot()) kopiert werden, denn das Paket kann ja eigentlich nicht live in das System integriert werden. (Würde man so z. B. mit der Glibc-Bibliothek vorgehen, würden wir /lib/libc.so überschreiben, während wir %install ausführen – bei Glibc ist das fatal.) Daher RPM_BUILD_ROOT. Natürlich müsste das Makefile entsprechend angepasst werden, so dass es PREFIX unterstützt, z. B.:
%install
[ "$RPM_BUILD_ROOT" != "/" -a -d "$RPM_BUILD_ROOT" ] && rm -Rf "$RPM_BUILD_ROOT";
make install PREFIX="$RPM_BUILD_ROOT"
Die Files-Sektion
Hier müssen Sie alle Dateien mit absolutem Pfad angeben, die in das Paket aufgenommen werden. Alles, was Sie nicht in der Files-Sektion angeben, wird nicht in das Paket aufgenommen und auch bei der Deinstallation nicht wieder entfernt. Allerdings mit RPM ab der Version 4 bricht rpm ab, wenn es nicht –in %files aufgelistete Dateien findet. Einige mögen das Verhalten störend finden, es dient jedoch zur Suche nach Fehlern. Schreiben Sie vor den Dateinamen ein %doc, wird die entsprechende Datei in einem Verzeichnis wie /usr/share/doc/[paketname] (Red Hat: /usr/doc/paketname) abgelegt. Wenn Sie in Ihrem Paket eine Manual Page eingerichtet haben, müssen Sie auch hierfür einen entsprechenden Pfad angeben. Eingeleitet wird die Files-Sektion mit %files. So könnte eine Files-Sektion wie folgt aussehen:
%files
%doc README
/usr/bin/mein_projekt
/usr/share/man/man1/mein_projekt.1
Hiermit hätten Sie im Verzeichnis /usr/share/doc/mein_projekt-0.1 bzw. /usr/doc/... eine Datei namens README, die Software selbst (in /usr/bin besser /usr/local/bin) und die Manual Page (in usr/share/man/man1/) in das Paket aufgenommen (immer vorausgesetzt, die Pfadangabe stimmt und Sie haben entsprechende Rechte). In unserem Beispiel reicht folgende Files-Sektion aus:
%files
/usr/bin/mein_projekt
17.3.5 Paket erstellen
Nachdem Sie für das Projekt die Spec-Datei fertig gestellt haben, können Sie diese in das SPECS-Verzeichnis verschieben.
Hinweis Damit auch alles so funktioniert, wie Sie es wollen und der Autor es beabsichtigt hatte, müssen (sofern nötig) natürlich die entsprechenden Pfadangaben an das eigene System angepasst werden. Kurz: Nicht immer bringt ein stures Copy & Paste (oder hier Read & Type) den gewünschten Erfolg.
|
Hier nochmals die komplette Spec-Datei namens mein_projekt.spec:
# Dies ist eine einfache Spec-Datei für ein einfaches Testprojekt
Summary: Ein Testprojekt zum Packen einer eigenen RPM
Name: mein_projekt
Version: 0.1
Release: 1
Copyright: GPL
Group: misc/mein_projekt
Source: ftp://ftp.pronix.de/mein_projekt/mein_projekt-0.1.tbz2
URL: http://pronix.de/mein_projekt/
Distribution: SUSE Linux 9.0
Vendor: Pronix Industries
Packager: Juergen Wolf <pronix@pronix.de>
%description
Bei diesem Paket handelt es sich um ein simples Beispiel,
um Ihnen das Erstellen eigener RPM-Pakete naeher zu erlaeutern.
%prep
%setup
%build
make
%install
cp "$RPM_BUILD_DIR"/mein_projekt-0.1/mein_projekt /usr/bin
%files
/usr/bin/mein_projekt
Diese Datei verschieben Sie jetzt wie folgt ins SPECS-Verzeichnis:
$ mv mein_projekt.spec /usr/src/packages/SPECS/
Jetzt können Sie in das SPECS-Verzeichnis wechseln und das Paket erstellen. Hierzu werden root-Rechte benötigt. Anschließend führen Sie mit RPMbuild die mein_projekt.spec-Datei mit dem Flag -ba (b für build) aus, womit ein Paket erstellt werden soll – a steht für all – was dafür sorgt, dass der komplette Vorgang auf einmal durchgeführt werden soll.
# cd /usr/src/packages/SPECS/
# rpm -ba mein_projekt.spec
Jetzt bekommen Sie eine Menge an Informationen um die Ohren gehauen, die sich in fünf Abschnitte aufteilen lassen:
|
die Ausgabe des %prep-Abschnitts |
|
die Ausgabe des %build-Abschnitts |
|
die Ausgabe des %install-Abschnitts |
|
die Ausgabe des %files-Abschnitts |
Mit der letzten und fünften Ausgabe wird praktisch das Paket erstellt:
Suche Provides: (benutze /usr/lib/rpm/find-provides)...
Suche Requires: (benutze /usr/lib/rpm/find-requires)...
Requires: ld-linux.so.2 libc.so.6 libc.so.6(GLIBC_2.0) libm.so.6
Geschrieben: /usr/src/packages/SRPMS/mein_projekt-0.1–1.src.rpm
Geschrieben: /usr/src/packages/RPMS/i386/mein_projekt-0.1–1.i386.rpm
Hierbei wird noch ausgegeben, welche Bibliotheken die Anwendung zum Übersetzen benötigt. In diesem Fall sollten mit den Bibliotheken
Requires: ld-linux.so.2 libc.so.6 libc.so.6(GLIBC_2.0) libm.so.6
auf keinem System irgendwelche Probleme auftreten. Jetzt haben Sie zwar ein fertiges Paket im Verzeichnis
Geschrieben: /usr/src/packages/SRPMS/mein_projekt-0.1–1.src.rpm
/usr/src/packages/RPMS/i386/mein_projekt-0.1–1.i386.rpm
aber dies ist erst die halbe Miete. Jetzt sollten Sie dieses Paket erst auf einem fremden Rechner testen, auf dem dieses Paket noch nicht installiert ist.
Einen Überblick über ein noch nicht installiertes RPM-Paket (-p) können Sie sich mit folgender Abfrage verschaffen:
$ rpm –iqp \
/usr/src/packages/RPMS/i386/mein_projekt-0.1–1.i386.rpm -i
Name : mein_projekt Relocations: (not relocateable)
Version : 0.1 Vendor: Pronix Industries
Release : 1
Build Date: Sam 10 Apr 2004 14:41:35 CEST
Install date: (not installed) Build Host: linux.local
Group : misc/mein_projekt
Source RPM: mein_projekt-0.1–1.src.rpm
Size : 11461 License: GPL
Packager : Jürgen Wolf <pronix@pronix.de>
URL : http://pronix.de/mein_projekt/
Summary : Ein Testprojekt zum Packen einer eigenen RPM
Description :
Bei diesem Paket handelt es sich um ein simples Beispiel,
um Ihnen das Erstellen eigener RPM-Pakete naeher zu erlaeutern.
Distribution: SUSE Linux 9.1
17.3.6 Das Paket installieren
Kommandozeile
Das Installieren von der Kommandozeile aus ist recht einfach zu realisieren (root):
# rpm -Uhv \
/usr/src/packages/RPMS/i386/mein_projekt-0.1–1.i386.rpm
KRPMView und Yast2
Mittlerweile lässt sich unter SUSE auch ein eigenes Paket mit Yast integrieren. Hierzu genügen ein einfacher Rechtsklick über dem Paket und das anschließende Anklicken von Vorschau in KRPMView. Jetzt nur noch auf den Button Installieren mit Yast drücken. Jetzt sollten Sie nach dem root-Passwort gefragt werden, und danach wird das Paket installiert.
Nun können Sie bei Yast die Paketgruppen auswählen und sollten dort einen neuen Reiter namens misc mit dem Paket mein_projekt vorfinden.
Hier finden Sie jetzt auch recht komfortabel die technischen Informationen, technischen Daten, Abhängigkeiten und Versionen des Pakets wieder.
KPackage
Natürlich muss es nicht immer SUSE mit Yast sein. Schließlich gibt es auch noch KPackage, womit Sie Ihre Pakete bequem installieren, löschen und erneuern können.
|