Entwicklerhandbuch/PaketverwaltungManuell

Aus Delixs
Zur Navigation springen Zur Suche springen

Diese Seite ist momentan eine Baustelle im Zustand: 2

Wird bearbeitet von: Hjg
Hilfe zum Bearbeitungsstatus: Hilfe:Status eines Artikels
Linux-Schulserver delixs
thumbs
Stammbaum
  \ Linux
    \ Debian
      \ delixs
Lizenz: GPL
Sprache: deutsch
Website: www.delixs.de

Einführung

In dieser Anleitung soll gezeigt werden, wie man einfache, debiankonforme Pakete erstellt und in das delixs-Repository hochlädt.

Vorarbeiten

Als Entwicklungsumgebung setze ich eine normale delixs aramec 0.10 Installation (bevorzugt als virtuelle Maschine) voraus. Hierauf müssen dann noch ein paar Tool installiert und konfiguriert werden.

Tools installieren

Installiere auf Deinem Rechner/VM die notwendigen Hilfsmittel mit folgendem Befehl:

 aptitude install dpkg-dev debhelper devscripts fakeroot dh-make build-essential 
                   gnupg gnupg-agent dput openssh-client

Repository konfigurieren

Das offizielle delixs-Repository muß in die apt-Konfiguration übernommen werden.

Erstelle bzw. editiere die Datei /etc/apt/sources.list.d/delixs.list :


 deb http://deb.delixs.de/ aramec/all/
 deb http://deb.delixs.de/ aramec/$(ARCH)/
 
 deb http://deb.delixs.de/ testing/all/
 deb http://deb.delixs.de/ testing/$(ARCH)/

Danach ein aptitude update und das Repository ist eingebunden.

Nun müssen noch die delixs-Schlüssel installiert werden, damit keine Sicherheitswarnungen entstehen:

 aptitude install delixs-archive-keyring

Danach wieder ein aptitude update, und das Repository ist offiziell verfügbar.

eigenen GPG-Schlüssel erzeugen

Da wir unsere Pakete später in das delixs-Repository hochladen wollen, müssen wir uns einen persönlichen GPG-Schlüssel generieren, mit dem die Pakete signiert werden. Unsignierte Pakete werden vom Repository nicht akzeptiert.

 $ gpg --gen-key
 Bitte wählen Sie, welche Art von Schlüssel Sie möchten:
  (1) DSA und Elgamal (voreingestellt)
  (2) DSA (nur unterschreiben/beglaubigen)
  (5) RSA (nur signieren/beglaubigen)
 Ihre Auswahl? 1
 
 Der DSA Schlüssel wird 1024 Bits haben.
 ELG-E-Schlüssel können zwischen 1024 und 4096 Bit lang sein.
 Welche Schlüssellänge wünschen Sie? (2048)
 
 Bitte wählen Sie, wie lange der Schlüssel gültig bleiben soll.
        0 = Schlüssel verfällt nie
       = Schlüssel verfällt nach n Tagen
     w = Schlüssel verfällt nach n Wochen
     m = Schlüssel verfällt nach n Monaten
     y = Schlüssel verfällt nach n Jahren
 Der Schlüssel bleibt wie lange gültig? (0) 5y
 
 Sie benötigen eine User-ID, um Ihren Schlüssel eindeutig zu machen; das
 Programm baut diese User-ID aus Ihrem echten Namen, einem Kommentar und
 Ihrer E-Mail-Adresse in dieser Form auf:
   ``Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>
 
 Ihr Name ("Vorname Nachname"): Herman Mustermann
 Email-Adresse: herman.mustermann@delixs.de
 Kommentar:
 Sie haben diese User-ID gewählt:
   "Herman Mustermann <herman.mustermann@delixs.de>"
 
 Ändern: (N)ame, (K)ommentar, (E)-Mail oder (F)ertig/(B)eenden? F
 
 Sie benötigen eine Passphrase, um den geheimen Schlüssel zu schützen.
 Passphrase: <sagichnicht>
 
 Wir müssen eine ganze Menge Zufallswerte erzeugen.  Sie können dies
 unterstützen, indem Sie z.B. in einem anderen Fenster/Konsole irgendetwas
 tippen, die Maus verwenden oder irgendwelche anderen Programme benutzen.
 ++++++++++.+++++.+++++.+++++++++++++++.++++++++++.++++++++++++++++++++.++++++

Es kann noch folgende Meldung erscheinen:

 Es sind nicht genügend Zufallswerte vorhanden.  Bitte führen Sie andere
 Arbeiten durch, damit das Betriebssystem weitere Entropie sammeln kann!
 (Es werden noch 283 Byte benötigt.)

Dann einfach eine weitere ssh-Sitzung bzw. Konsole öffnen und sinnfreie Tasten drücken. Bei genügend Tastendrücken fährt das gpg-Programm automatisch fort.

 gpg: /home/mustermann/.gnupg/trustdb.gpg: trust-db erzeugt
 gpg: Schlüssel 55248F5E ist als uneingeschränkt vertrauenswürdig gekennzeichnet
 Öffentlichen und geheimen Schlüssel erzeugt und signiert.
 
 gpg: "Trust-DB" wird überprüft
 gpg: 3 marginal-needed, 1 complete-needed, PGP Vertrauensmodell
 gpg: Tiefe: 0  gültig:   1  unterschrieben:   0  Vertrauen: 0-, 0q, 0n, 0m, 0f, 1u
 gpg: nächste "Trust-DB"-Pflichtüberprüfung am 2015-01-19
 pub   1024D/D45554A1 2010-01-20 [verfällt: 2015-01-19]
   Schl.-Fingerabdruck = DF97 B5EA 32A4 E53C 8EA5  1310 E230 87B2 D455 54A1
   uid                  Herman Mustermann <herman.mustermann@delixs.de>
   sub   2048g/B93FC568 2010-01-20 [verfällt: 2015-01-19]

Wir haben uns hiermit nun einen DSA/ElGamal-Schlüssel erzeugt, der 2048 Bits groß ist und 5 Jahre gültig sein wird.

Der öffentliche Teil des Schlüssels muss natürlich irgendwie zugänglich sein, man sollte ihn daher mit folgendem Befehl exportieren:

 $ gpg --armor --export herman.mustermann@delixs.de > pgp-mustermann.asc

dput und ssh konfigurieren

Die Pakete werden später mit dem Tool 'dput' hochgeladen. Damit dieses Programm weiß, was es tun soll, erstellen wir in unserem Homeverzeichnis die Datei '.dput.cf':

 ~/.dput.cf:
 [delixs]
 fqdn          = deb.delixs.de
 method        = scp
 login         = dupload
 incoming      = ./incoming
 run_dinstall  = 0
 allow_unsigned_uploads = 0
 verify_sigs = 1

dput verwendet für das Login auf dem Server 'deb.delixs.de' den User 'dupload'.
Zur Identifikation werden zwei Schlüsseldateien benötigt, die wir auf Anforderung via PM von Thorsten erhalten.

Die Key-Dateien des Repository-Verwalters 'dupload' werden einkopiert:
Falls noch nicht vorhanden, zuerst das Verzeichnis ~/.ssh erstellen, dann id_dupload.pub und id_dupload nach ~/.ssh kopieren.
Abschließend müssen der Datei id_dupload andere Zugriffsrechte gegeben werden:

 chmod 600 id_dupload

Da die Kommunikation mit dem Repository verschlüsselt erfolgt, müssen wir eine entsprechende ssh-Konfiguration erstellen.

 ~/.ssh/config:
 host deb.delixs.de
   User dupload
   Ciphers arcfour
   IdentityFile ~/.ssh/id_dupload
   Compression yes

Unser Homeverzeichnis sieht nun also ungefähr so aus:

 |-- .bash_history
 |-- .bash_logout
 |-- .bashrc
 |-- .dput.cf
 |-- .gnupg
 |   |-- gpg.conf
 |   |-- pubring.gpg
 |   |-- random_seed
 |   |-- secring.gpg
 |   `-- trustdb.gpg
 |-- .ssh
 |   |-- config
 |   |-- id_dupload
 |   `-- id_dupload.pub
 `-- pgp-mustermann.asc

Arbeitsverzeichnis erstellen

Ab jetzt wollen wir fleissig sein und viele Debianpakete veröffentlichen.
Deshalb erstellen wir uns ein Arbeitsverzeichnis für alle neuen Pakete und wechseln dorthin:

 mkdir ~/debianpakete
 cd ~/debianpakete

Neues Projekt

Wir beginnen mit einem neuen Projekt, indem wir einen zugehörigen Unterordner erstellen.
In diesem Unterordner werden alle Versionen und Paketdateien gesammelt.

Projektordner erstellen:

 mkdir ./delixs-test-script
 cd delixs-test-script

Nun wollen wir die erste Version unseres Projekts angehen und erstellen uns dafür ein entsprechendes Arbeitsverzeichnis.
Die Benennung dieses Verzeichnisses ist nicht ganz unwichtig, da der Name auch gleichzeitig die Versionsnummer beinhalten soll. Generell sollte das Muster 'paketname-version' eingehalten werden, wie z.B. in 'delixs-test-script-0.1'. Bitte nur Buchstaben, Zahlen und Bindestriche verwenden (also keine Unterstriche !).

Arbeitsverzeichnis erstellen:

 mkdir ./delixs-test-script-0.1
 cd delixs-test-script-0.1

Im nächsten Schritt müssen wir ein Verzeichnis erstellen, dessen Inhalt der Paketmanager für die Verwaltung und die einzelnen Installationsphasen benötigt.
Das machen wir aber nicht manuell, sondern nutzen dafür das Tool 'dh_make'. Es erstellt einen Unterordner 'debian' und füllt ihn mit den notwendigen und bereits auf unser Projekt angepassten Steuerungsdateien.

Paketverzeichnis 'debian' erstellen mit:

 export DEBFULLNAME="Herman Mustermann"; dh_make -n -s -e herman.mustermann@delixs.de
 
 (wobei -n = native package
 	 -s = single binary
 	 -e = maintainer email address
 bedeutet)

Zur Sicherheit habe ich dem Tool über eine Umgebungsvariable meinen vollständigen Namen übergeben (der in den vom Tool zu erzeugenden Dateien eingetragen werden soll). dh_make ist zwar in der Lage, diesen Namen aus meiner Standardumgebung zu extrahieren, aber wenn ich mich mal nicht als 'Mustermann' angemeldet habe, sondern z.B. sträflicherweise als User 'root' arbeite, ist dieser Mechanismus ganz sinnvoll :-)

Das Tool meldet:

 Maintainer name : Herman Mustermann
 Email-Address   : herman.mustermann@delixs.de
 Date            : Tue, 19 Jan 2010 19:40:56 +0100
 Package Name    : delixs-test-script
 Version         : 0.1
 License         : gpl
 Using dpatch    : no
 Type of Package : Single
 Hit <enter> to confirm:

Mit einem beherzten Druck auf die Enter-Taste bestätigen wir die Rahmendaten unseres Projekts.

dh_make meldet danach den Vollzug:

 Currently there is no top level Makefile. This may require additional tuning.
 Done. Please edit the files in the debian/ subdirectory now. You should also
 check that the delixs-test-script Makefiles install into $DESTDIR and not in / .

Wir gehen in das neue Verzeichnis und sehen uns um.

 cd debian

Wir erkennen schnell, dass unser Tool dort viele Dateien angelegt hat, die wir glücklicherweise zum großen Teil erst mal gar nicht benötigen. Respektive die Beispieldateien mit der Endung '.ex' können wir erst mal zur Seite legen oder auch gleich ganz löschen.

Dateien löschen:

 rm *.ex *.EX

Unsere Verzeichnisstruktur sieht nun also ungefähr so aus:

 |-- debianpakete
 |   `-- delixs-test-script
 |       `-- delixs-test-script-0.1
 |           `-- debian
 |               |-- README
 |               |-- README.Debian
 |               |-- changelog
 |               |-- compat
 |               |-- control
 |               |-- copyright
 |               |-- dirs
 |               |-- docs
 |               `-- rules

Wir müssen nun noch einige Dateien editieren.

Datei 'control'
Diese Datei enthält einen Überblick über unser Paket, also eine Beschreibung, eventuelle Abhängigkeiten von anderen Paketen etc.
Der Inhalt ist im Wesentlichen selbsterklärend; wir müssen auf jeden Fall folgende Zeilen bearbeiten.

Anpassen 'control':

 Section: mail
 Homepage: www.delixs.de
 Architecture:all
 Description: ...

Debian-Pakete werden im Standard-Debian-Archiv eingeteilt in 'main', 'contrib' und 'non-free'. Innerhalb dieser Bereiche gibt es noch 'Sections' (also Unterbereiche), in die Pakete einsortiert werden.
Unser neues Paket sollte einer dieser Sections zugeordnet werden. Als 'Section' tragen wir z.B. 'mail', 'misc', 'net' o.ä. ein. Eine vollständige Liste dieser Sections gibt es unter http://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections

Als 'Homepage' setzen wir unsere Projekt-Website ein: www.delixs.de
Als 'Architecture' nehmen wir 'all', da unser Paket (vorerst) keine kompilierten und somit prozessorarchitekturbedingten Dateien enthält.
Die 'Description', also Beschreibung unseres Pakets, ist zweiteilig. Direkt hinter 'Description' setzen wir eine kurze, einzeilige Beschreibung, in die Zeile(n) darunter, mit einem Leerzeichen am Anfang jeder Zeile, verfassen wir eine ausführlichere Beschreibung unseres Projekts.

Im Ergebnis sieht das Ganze dann ungefähr so aus:

 Source: delixs-test-script
 Section: misc
 Priority: extra
 Maintainer: Herman Mustermann <herman.mustermann@delixs.de>
 Build-Depends: debhelper (>= 7)
 Standards-Version: 3.7.3
 Homepage: www.delixs.de
 
 Package: delixs-test-script
 Architecture: all
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Description: Test script for the delixs project.
  This is a rather lengthy description of a small package which will serve as
  an example of building debian packages for the delixs project.

Datei 'changelog'
Wie der Name schon vermuten lässt, sollen in dieser Datei die Änderungen an unserem Paket von Version zu Version fortgeschrieben werden.
Unser Tool dh_make hat uns hier schon mal eine Grundstruktur eingetragen, die wir aber noch in einem Punkt anpassen müssen.
In der ersten Zeile steht:

 delixs-test-script (0.1) unstable; urgency=low

Das 'unstable' hinter der Versionsnummer bestimmt, in welchen Debianzweig unser Paket später hochgeladen wird. Für das delixs-Projekt wurden die Zweige 'aramec' und 'testing' eingerichtet, entsprechend müssen wir hier statt 'unstable' also entweder 'testing' oder 'aramec' eintragen.
Da unser neues Paket ja noch nicht für den produktiven Einsatz freigegeben ist, werden wir hier also 'testing' verwenden.

Die Dateien 'README' und 'copyright' sind sicherlich selbsterklärend und können nach Bedarf angepasst werden.

Datei 'rules'
Dies ist die zentrale Steuerungsdatei, die für alle Instalationsarbeiten vom Paketmanager aufgerufen wird.
Es handelt sich hierbei um eine Make-Steuerungsdatei, die auf den ersten Blick etwas unübersichtlich erscheint. Wir müssen uns auch jetzt noch nicht in die Details dieser Datei einarbeiten, aber um unser Paket für einen ersten Build-Lauf formal korrekt aufzustellen, sollten wir zunächst drei Zeilen darin editieren.

In diesen Zeilen befindet sich der Aufruf eines weiteren Makefiles, das wir aber noch gar nicht erstellt haben (und es vielleicht auch nie tun werden).
Deshalb werden wir den Aufruf einfach auskommentieren, indem wir an den Anfang der jeweiligen Zeile eine Raute '#' setzen.

Anpassen 'rules':

 Zeile 30: #<----->$(MAKE)
 Zeile 41: #<----->$(MAKE) clean
 Zeile 53: #<----->$(MAKE) DESTDIR=$(CURDIR)/debian/delixs-test-script install

Der Build-Vorgang

So, nun können wir einmal testweise versuchen, ob die Paketerstellung soweit funktioniert.

Wir geben ein:

 debuild

Die Ausgabe ist etwas geschwätzig:

 mustermann@alix:~/debianpakete/delixs-test-script/delixs-test-script-0.1$ debuild    
 dpkg-buildpackage -rfakeroot -D -us -uc
 dpkg-buildpackage: setze CFLAGS auf Standardwert: -g -O2
 dpkg-buildpackage: setze CPPFLAGS auf Standardwert:
 dpkg-buildpackage: setze LDFLAGS auf Standardwert:
 dpkg-buildpackage: setze FFLAGS auf Standardwert: -g -O2
 dpkg-buildpackage: setze CXXFLAGS auf Standardwert: -g -O2
 dpkg-buildpackage: Quellpaket delixs-test-script
 dpkg-buildpackage: Quellversion 0.1
 dpkg-buildpackage: Quellen geändert durch Herman Mustermann <herman.mustermann@delixs.de>
 dpkg-buildpackage: Host-Architektur i386
  fakeroot debian/rules clean
 dh_testdir
 dh_testroot
 rm -f build-stamp configure-stamp
 # Add here commands to clean up after the build process.
 dh_clean
  dpkg-source -b delixs-test-script-0.1
 dpkg-source: Information: verwende Quellformat »1.0«
 dpkg-source: Information: baue delixs-test-script in delixs-test-script_0.1.tar.gz
 dpkg-source: Information: baue delixs-test-script in delixs-test-script_0.1.dsc
  debian/rules build
 dh_testdir
 # Add here commands to configure the package.
 touch configure-stamp
 dh_testdir
 # Add here commands to compile the package.
 #docbook-to-man debian/delixs-test-script.sgml > delixs-test-script.1
 touch build-stamp
  fakeroot debian/rules binary
 dh_testdir
 dh_testroot
 dh_clean -k
 dh_installdirs
 # Add here commands to install the package into debian/delixs-test-script.
 dh_testdir
 dh_testroot
 dh_installchangelogs
 dh_installdocs
 dh_installexamples
 dh_installman
 dh_link
 dh_strip
 dh_compress
 dh_fixperms
 dh_installdeb
 dh_shlibdeps
 dh_gencontrol
 dpkg-gencontrol: Warnung: unbekannte Substitutionsvariable ${shlibs:Depends}
 dpkg-gencontrol: Warnung: unbekannte Substitutionsvariable ${misc:Depends}
 dh_md5sums
 dh_builddeb
 dpkg-deb: Baue Paket »delixs-test-script« in »../delixs-test-script_0.1_all.deb«
 .
  dpkg-genchanges  >../delixs-test-script_0.1_i386.changes
 dpkg-genchanges: füge kompletten Quellcode beim Hochladen hinzu
 dpkg-buildpackage: Alles hochzuladen; Debian-native-Paket (komplette Quellen enthalten)
 Now signing changes and any dsc files...
  signfile delixs-test-script_0.1.dsc Herman Mustermann <herman.mustermann@delixs.de>
 
 Sie benötigen eine Passphrase, um den geheimen Schlüssel zu entsperren.
 Benutzer: "Herman Mustermann <herman.mustermann@delixs.de>"
 1024-Bit DSA Schlüssel, ID D45554A1, erzeugt 2010-01-20
 
 
  signfile delixs-test-script_0.1_i386.changes Herman Mustermann <herman.mustermann@delixs.de>
 
 Sie benötigen eine Passphrase, um den geheimen Schlüssel zu entsperren.
 Benutzer: "Herman Mustermann <herman.mustermann@delixs.de>"
 1024-Bit DSA Schlüssel, ID D45554A1, erzeugt 2010-01-20
 
 
 Successfully signed dsc and changes files

Wie man sieht, wird das Paket zunächst zusammengebaut und dann signiert.
Es wird sowohl das Paket (bzw. seine Beschreibung) als auch die zum Paket gehörende Changes-Datei signiert, weshalb auch zweimal nach dem Password gefragt wird, das wir bei der Erzeugung unseres GPG-Schlüssels definiert hatten.

Schauen wir uns mal kurz an, was der Befehl 'debuild' denn eigentlich gemacht hat. Dazu wechseln wir von unserem debian-Verzeichnis zwei Ebenen weiter nach oben und finden dort folgende Struktur:

 |-- delixs-test-script-0.1
 |   |-- build-stamp
 |   |-- configure-stamp
 |   `-- debian
 |       |-- README
 |       |-- README.Debian
 |       |-- changelog
 |       |-- compat
 |       |-- control
 |       |-- copyright
 |       |-- delixs-test-script
 |       |   |-- DEBIAN
 |       |   |   |-- control
 |       |   |   `-- md5sums
 |       |   `-- usr
 |       |       |-- bin
 |       |       |-- sbin
 |       |       `-- share
 |       |           `-- doc
 |       |               `-- delixs-test-script
 |       |                   |-- README.Debian
 |       |                   |-- changelog.gz
 |       |                   `-- copyright
 |       |-- delixs-test-script.debhelper.log
 |       |-- dirs
 |       |-- docs
 |       |-- files
 |       `-- rules
 |-- delixs-test-script_0.1.dsc
 |-- delixs-test-script_0.1.tar.gz
 |-- delixs-test-script_0.1_all.deb
 |-- delixs-test-script_0.1_i386.build
 `-- delixs-test-script_0.1_i386.changes

In unserem Paketverzeichnis finden wir nun neben dem 'debian'-Ordner auch noch ein paar neue Dateien, u.a. unser erstes Paket 'delixs-test-script_0.1_all.deb'.

Prima, das könnten wir nun einfach direkt installieren (mit 'dpkg -i delixs-test-script_0.1_all.deb', das Entfernen geht mit 'dpkg -P delixs-test-script'), aber das wäre natürlich unnütz, da unser Paket ja noch garnichts beinhaltet.

Trotzdem können wir herausfinden, was bei einer Installation unseres Pakets passieren würde, indem wir einfach mal einen Blick in unser 'debian'-Verzeichnis bzw. das darin entstandene Verzeichnis 'delixs-test-script' werfen.
In dieses Verzeichnis hat der Build-Befehl schon mal die Ordner und Dateien einkopiert, die auch bei einer realen Installation entstehen würden, in unserem Fall also ist das die Paket-Dokumentation in /usr/share/doc/delixs-test-script.
Ist zwar noch nicht weltbewegend, aber immerhin ...

Upload ins Repository

Nachdem wir nun so ein schönes Paket geschnürt haben, wollen wir es in das Projekt-Repository hochladen, damit alle Teammitglieder Freude daran haben.

Wir befinden uns im Ordner 'delixs-test-script-0.1' und sagen:

 dput delixs delixs-test-script_0.1_i386.changes

Wir sagen damit dput, dass es ins Repository 'delixs' hochladen soll; was und wohin hochgeladen werden soll, erkennt dput am Inhalt der *.changes Datei.

Wenn ein Paket erst einmal ins Repository hochgeladen wurde, ist ein nochmaliges Hochladen nicht mehr möglich, selbst wenn wir viele Änderungen vorgenommen und das Paket neu mit debuild erstellt haben (?). Ein Hochladen ist erst wieder möglich, wenn wir eine neue Version des Paketes erstellt haben.

Es dauert übrigens bis zu 15 Minuten, bis unser Paket vom Server verarbeitet und wirklich in das Repository aufgenommen wird.

Danach reicht ein

 aptitude update

und dann ein

 aptitude search delixs

um das eigene, neue Paket im Repository zu sehen.

Neue Version

Nachdem wir das Grundpaket erfolgreich erstellt haben, werden wir nun eine neue Version des Paketes angehen, die dann auch mal etwas Sinnvolles tut.

Um eine neue Version zu erzeugen, gehen wir zunächst in das Verzeichnis der aktuellen Version

 cd ~/debianpakete/delixs-test-script/delixs-test-script-0.1

Wir initiieren die neue Version mit

 debchange -im
 ( wobei   -i  inkrementiere die Versionsnummer
           -m  behalte die bisherigen Maintainerdaten bei
 bedeutet)

Es startet der Editor und zeigt uns die Datei 'changelog', die nun schon durch einen neuen Eintrag 'delixs-test-script (0.2)' erweitert wurde.

Wir können die Datei um einen entsprechenden Kommentar ergänzen und abspeichern/beenden.

debchange meldet uns zum Abschluss:

 debchange warning: your current directory has been renamed to:
 ../delixs-test-script-0.2

Es hat also unser Versionsverzeichnis umbenannt, indem es die Versionsnummer am Ende hochzählt.
Wir wechseln in dieses Verzeichnis.

Paket-Beispiele

Ein PHP-Script-Paket

Wir möchten gerne, dass unser Paket ein PHP-Script installiert, das wir dann über einen Webbrowser aufrufen können.

Wir erstellen das PHP-Script im Verzeichnis 'delixs-test-script-0.2'.

 mcedit HelloWorld.php
 <?php
   echo "Hello world !";
 ?>

Nun müssen wir dem Paketmanager noch sagen, dass dieses Script in den Dokumentenbereich des apache installiert werden soll.
Hierzu wechseln wir in das 'debian'-Verzeichnis und erstellen die Datei 'install'

 cd debian
 mcedit install
 HelloWorld.php  var/www/htdoc/hwscript

Ein Einzeiler, der bewirkt, dass die Datei 'HelloWorld.php' während der Installation unseres Paketes in das Verzeichnis /var/www/htdocs/hwscript kopiert wird.
(Syntax: quelldatei zielverzeichnis)

Hätten wir mehrere Dateien dorthin zu kopieren, würde der Einzeiler so aussehen:

 HelloWorld.php HelloUniverse.php  var/www/htdoc/hwscript

(Syntax: quelldatei[ quelldatei] zielverzeichnis)

Wir können auch ein komplettes Verzeichnis (samt evtl. darin liegenden Verzeichnisbaum) installieren:

 PHP-scripte/  var/www/htdoc/hwscript

(Syntax: quellverzeichnis/ zielverzeichnis)

Damit der Paketmanager die 'install'-Datei auswertet, müssen wir noch kurz die zentrale Steuerungsdatei 'rules' editieren.

In Zeile 66 entfernen wir das Kommentarzeichen vom Zeilenanfang.

 #<----->dh_install

und speichern ab. Fertig.

Das wollen wir gleich mal testen. Wir erstellen das Paket mit

 debuild

und finden nun unterhalb des 'debian'-Verzeichnisses folgende Struktur:

 |-- delixs-test-script
 |   |-- DEBIAN
 |   |   |-- control
 |   |   `-- md5sums
 |   |-- usr
 |   |   |-- bin
 |   |   |-- sbin
 |   |   `-- share
 |   |       `-- doc
 |   |           `-- delixs-test-script
 |   |               |-- README.Debian
 |   |               |-- changelog.gz
 |   |               `-- copyright
 |   `-- var
 |       `-- www
 |           `-- htdoc
 |               `-- hwscript
 |                   `-- HelloWorld.php

Sieht gut aus, aber wir wollen uns an der Realität messen, deshalb installieren wir das Paket mit

 dpkg -i delixs-test-script_0.2_all.deb 

starten einen Webbrowser und geben ein:

 http://10.100.0.1/hwscript/HelloWorld.php

q.e.d. :-)

Genauso schnell werden wir das Paket auch wieder los:

 dpkg -P delixs-test-script

Ein Fremd-Paket installieren

Wir wollen ein fremdes, bereits für Debian existierendes Paket installieren und dabei delixs-spezifische Einstellungen bzw. Anpassungen vornehmen.
Als Beispiel nehmen wir das Paket 'cron-apt', das regelmäßig nach neuen Updates für unseren Server sucht und den Systembetreuer über neue Versionen informiert.

Grundgerüst

Hierzu legen wir ein neues Projekt- und Versionsverzeichnis an

 cd ~/debianpakete
 mkdir ./delixs-refresh
 cd delixs-refresh
 mkdir ./delixs-refresh-0.1
 cd delixs-refresh-0.1

Paketverzeichnis 'debian' erstellen mit:

 export DEBFULLNAME="Herman Mustermann"; dh_make -n -s -e herman.mustermann@delixs.de

Wir gehen in das neue Verzeichnis und löschen die überflüssigen Dateien. Vor dem Löschen benennen wir aber erst noch zwei der Beispieldateien um, die wir später noch benötigen.

 cd debian
 mv postinst.ex postinst
 mv postrm.ex postrm
 rm *.ex *.EX

Wir passen wie üblich die wichtigsten Dateien an.

Anpassen 'control':

 Section: admin
 Homepage: www.delixs.de
 Architecture:all
 Description: update notifiation of packages for delixs ...

Zusätzlich zu den bekannten Feldern werden wir 'Depends' um das zu installierende Fremdpaket ergänzen.

Info: Das Installationssystem prüft vor der Installation unserer eigenen Dateien, ob unser Paket von anderen Paketen abhängig ist. Falls dem so sein sollte ('Depends: ...'), werden zunächst die aufgeführten anderen Pakete installiert und konfiguriert, bevor unsere eigenen Dateien an die Reihe kommen.
Deshalb müssen wir lediglich definieren, dass unser Paket von 'cron-apt' abhängt, um dieses Paket automatisch installiert zu bekommen.

Im Ergebnis sieht das Ganze dann ungefähr so aus:

 Source: delixs-refresh
 Section: admin
 Priority: extra
 Maintainer: Herman Mustermann <herman.mustermann@delixs.de>
 Build-Depends: debhelper (>= 7)
 Standards-Version: 3.7.3
 Homepage: www.delixs.de
 
 Package: delixs-refresh
 Architecture: all
 Depends: ${shlibs:Depends}, ${misc:Depends}, cron-apt
 Description: update notifiation of packages for delixs
  This package installs the tool cron-apt and changes its configuration to gain.
  a perfectly everytime up-to-date delixs server.

Datei 'changelog'

 delixs-refresh (0.1) testing; urgency=low

Anpassen 'rules':

 Zeile 30: #<----->$(MAKE)
 Zeile 41: #<----->$(MAKE) clean
 Zeile 53: #<----->$(MAKE) DESTDIR=$(CURDIR)/debian/delixs-test-script install

Schnell mal testen, ob die Paketerstellung soweit funktioniert.

 debuild

Es fragt nach unserem GPG-Password und erstellt das Paket ohne Fehlermeldung - prima.

Paket konfigurieren

Wenn unser Paket später installiert wird, hat ja der Paketmanager durch die 'Depends'-Angabe dafür gesorgt, dass das Fremdpaket 'cron-apt' vor unseren eigenen Dateien installiert wurde. Wir greifen also auf ein fertig installiertes 'cron-apt' zu.
Nun haben wir gar keine eigenen Dateien, die es zu instalieren gäbe (die 'install'-Datei wird nicht benötigt). Statt dessen wollen wir lediglich einige Konfigurationsdateien ändern, und der Ansatzpunkt hierfür ist die Steuerungsdatei 'postinst'. Wie der Name vermuten läßt, wird dieses Programm ausgeführt, nachdem alle Dateien unseres Pakets installiert wurden.

Zunächst markieren wir 'postinst' als executable.

 chmod 755 postinst

Und editieren dann die Datei.
Schnell sehen wir, dass sie eigentlich nur aus einer rudimentären case-Abfrage besteht, deren 'configure)'-Zweig für uns wichtig ist. Hier tragen wir die Befehle ein, um Änderungen an der Konfiguration des Fremdpakets vorzunehmen.

Wir erstellen zwei Funktionen, die im Case-Zweig aufgerufen werden.

 #!/bin/sh
 # postinst script for delixs-refresh
 #
 # see: dh_installdeb(1)
 set -e
 
 set_config() {
   # cron-apt config anpassen:
   FILE=/etc/cron-apt/config
   echo "  cron-apt default config"
   sed -i -e "s:^# APTCOMMAND=/usr/bin/aptitude:APTCOMMAND=/usr/bin/aptitude:" \
       -e "s/^# MAILTO=\"root\"/MAILTO=\"postmaster\"/" \
       -e "s/^# MAILON=\"error\"/MAILON=\"upgrade\"/" \
       ${FILE}
   if [ $? -gt 0 ] ; then
       echo "  Fehler beim Bearbeiten der Datei ${FILE}"
       exit 2
   fi
 }
 
 set_action() {
   # cron-apt action script setzen:
   FILE=/usr/share/doc/cron-apt/examples/9-notify
   echo "  cron-apt action script"
   cp ${FILE} /etc/cron-apt/action.d/9-notify
   if [ $? -gt 0 ] ; then
       echo "  Fehler beim Bearbeiten der Datei ${FILE}"
       exit 2
   fi
 }
 
 case "$1" in
   configure)
       set_config
       set_action
   ;;
 
   abort-upgrade|abort-remove|abort-deconfigure)
   ;;
 
   *)
       echo "postinst called with unknown argument \`$1'" >&2
       exit 1
   ;;
 esac
 # dh_installdeb will replace this with shell code automatically
 # generated by other debhelper scripts.

Das sollte genügen.
Wir erstellen das Paket

 debuild

und laden es in das Repository hoch.

 cd ~/debianpakete/delixs-refresh
 dput delixs delixs-refresh_0.1_i386.changes

Ein Test mit 'dpkg -i ...' ist leider nicht möglich, da dpkg im Gegensatz zu aptitude keine Abhängigkeiten auflösen kann. Aptitude hingegen kann nur Pakete aus Repositories installieren.

Wir warten 15 Minuten auf das Update des Repositorys und installieren dann unser Paket

 aptitude update
 aptitude install delixs-refresh

Ein kurzer Blick in die Konfigurationsdateien unter /etc/cron-apt zeigt uns, dass das Fremdpaket einwandfrei installiert und unsere Anpassungen ebenso übernommen wurden.

Deinstallation verbessern

Im Prinzip sind wir fertig, allerdings sollten wir noch eine Unzulänglichkeit im Zusammenhang mit der Deinstallation abstellen.
Es gibt unter der Debian-Paketverwaltung zwei Stufen der Deinstallation. Wenn 'aptitude remove ...' aufgerufen wird, entfernt der Paketmanager wie erwartet alle Dateien, die er vormals installiert hatte.
Ausnahmen bilden allerdings Dateien, die typischerweise unter '/etc' liegen und als Konfigurationsdateien definiert sind. Die werden nicht gelöscht, denn falls man das Paket später mal wieder installieren möchte, lägen dann schon angepasste Konfigurationen wie beim letzten Lauf bereit.

Um aber auch diese Dateien loszuwerden, gibt es den Befehl 'aptitude purge ...', der dann wirklich alle Reste des Pakets und Eintragungen in der Paketmanagerdatenbank entfernt.

Wenn wir diesen Befehl auf unser 'delixs-refresh'-Paket bzw. das Fremdpaket cron-apt anwenden, sehen wir eine Fehlermeldung:

 Lösche Konfigurationsdateien von cron-apt ...
 dpkg - Warnung: Während Entfernens von cron-apt ist Verzeichnis »/etc/cron-apt/action.d« 
 nicht leer, wird daher nicht gelöscht.

Klar, wir haben ja in der postinst dafür gesorgt, dass eine weitere Action-Datei einkopiert wird, deshalb müssen wir dafür sorgen, dass diese Datei entsprechend entsorgt wird.

Hierzu erhöhen wir zunächst unsere Version

 debchange -im

Handelte es sich bei der zu löschenden Datei um ein File, das auch durch unser Paket installiert wurde, genügte es, im 'debian'-Verzeichnis die Datei 'conffiles' anzulegen.

 mcedit conffile
 /etc/cron-apt/action.d/9-notify

Damit hätten wir '9-notify' als Konfigurationsdatei definiert, und es wäre schon alles erledigt, den Rest übernähme der Paketmanager.

Aber leider stammt diese Datei ja aus dem Fremdpaket 'cron-apt', deshalb können wir diesen leichten Weg nicht gehen, sondern müssen die von uns einkopierte Datei auch selbst wieder löschen.

Wir bedienen uns der Datei 'postrm', die vom Paketmanager aufgerufen wird, nachdem er seine Löscharbeiten erledigt hat.
Zunächst markieren wir 'postrm' als executable.

 chmod 755 postrm

Und editieren dann die Datei.

Auch bei dieser Vorlage handelt es sich im wesentlichen nur um eine Case-Abfrage, bei der wir den 'purge'-Fall separieren:

 #!/bin/sh
 # postrm script for delixs-refresh
 #
 # see: dh_installdeb(1)
 
 set -e
 
 case "$1" in
   remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
   ;;
 
   purge)
       rm /etc/cron-apt/action.d/9-notify
   ;;
 
   *)
       echo "postrm called with unknown argument \`$1'" >&2
       exit 1
   ;;
 esac
 
 # dh_installdeb will replace this with shell code automatically
 # generated by other debhelper scripts.
 
 #DEBHELPER#
 
 exit 0

Fertig.


Fragen und Antworten

Manchmal ist es notwendig, zur ordnungsgemäßen Konfiguration eines Paketes zusätzliche Informationen vom Benutzer einzuholen.
Der Paketmanager bringt alle Tools mit, um dem Anwender unabhängig von der gerade verwendeteten (Text- oder Grafik-) Oberfläche die gewünschten Fragen zu präsentieren und dessen Antworten systemweit - und somit auch für den Zugriff durch andere Pakete - in einer Datenbank abzulegen.

Bemerkenswert hierbei ist die Tatsache, dass die Präsentation der Fragen asynchron zur Paketinstallation und Konfiguration erfolgt.
Wenn dem Paketmanager mehrere Pakete zur Installation übergeben werden, durchforstet er sie zunächst auf irgendwelche Fragen, die es zu stellen gilt, fasst diese Fragen aus allen Paketen zusammen und bietet sie dem Anwender zur Beantwortung an.
Die Antworten werden in der Datenbank gespeichert, und erst dann erfolgt die normale Installation der einzelnen Pakete. Während der Installation kann ein Paket dann auf diese Datenbank zurückgreifen und sich die Antworten abholen, die es benötigt.

Diese Ansynchronität zwischen Fragestellung und Installation/Konfiguration wird auch in der Art der Implementierung bei der Paketerstellung deutlich.

Das sehen wir uns am Beispiel unseres Pakets 'delixs-refresh' an.
In dem Paket 'cron-apt' wird u.a. ein cron-Job eingerichtet, der einmal täglich nach Updates sucht. Wir möchten, dass der User bestimmen kann, um welche Uhrzeit diese Updatesuche durchgeführt wird.

Wir wechseln in unser Projektverzeichnis, erhöhen auf eine neue Version, und gehen dann in das 'debian'-Verzeichnis.

 cd ~/debianpakete/delixs-refresh/delixs-refresh-0.3
 debchange -im
 cd debian

Dort legen wir zunächst die Datei 'templates' an, in der wir unsere Frage(n) definieren.

 mcedit templates
 Template: delixs-refresh/cron-time
 Type: string
 Default: 4
 Description: When should cron-apt search for new updates:
  Enter the time of day at which cron-apt should get new updates.
 Description-de.UTF-8: Wann soll cron-apt nach neuen Updates suchen:
  Bitte geben Sie die Uhrzeit an, zu der cron-apt neue Updates abruft.

Der Aufbau dieser Datei ist recht einfach.
Eine Frage wird eingeleitet durch die Definition eines eindeutigen Namens, Angabe des Typs, eines zu erwartenden Standardwertes und der textuellen Kurz- und Lang-Definition der Frage an sich; zunächst in Englisch, dann optional in anderen Sprachen. Mehrere Fragen werden durch eine Leerzeile getrennt.

 Template: <paketname>/<fragen-bezeichnung>
 Type: select | multiselect | string | boolean | note | text | password
 Default: <default value>
 Description: Blah blah blah?
  Blah blah blah. Blah blah. Blah blah blah. Blah blah? Blah
  blah blah blah. Blah blah blah. Blah blah.
 Description-<lang>: Blah blah blah?
  Blah blah blah. Blah blah. Blah blah blah. Blah blah. Blah blah blah.
  blah.
 
 Template: ....
 ....

Als nächstes müssen wir dem Paketmanager noch mitteilen, in welcher Reihenfolge unsere Fragen zu stellen sind, evtl. Antworten auf Fehleingaben überprüfen etc. Hierfür erstellen wir die Scriptdatei 'config'.

 touch config
 chmod 755 config
 mcedit config
 #!/bin/sh
 # config script for delixs-refresh
 #
 
 set -e
 
 . /usr/share/debconf/confmodule
 
 db_version 2.0
 
 # Fragen in gewuenschter Reihenfolge
 db_input high delixs-refresh/cron-time || true
 db_input high delixs-refresh/zweite-frage || true
 ...
 db_go
 
 # Eingaben pruefen:
 db_get delixs-refresh/cron-time
 ret=$(echo $RET | tr -cd '[:digit:]')
 if [ "$ret" != "$RET" ] || [ "x$ret" = "x" ] ; then
    # Fehlerbehandlung, da Eingabe keine Zahl ...
 fi
 
 db_stop
 
 exit 0

Erläuterung:
Zuerst werden die Routinen des Fragesystems eingebunden (confmodule) und dann mit 'db_input' die zu stellenden Fragen aufgelistet.
Ein 'db_go' weist das System an, die Fragen nun zu stellen und deren Antworten in der Datenbank zu speichern.
Mit 'db_get' wird die Datenbank nach einer Antwort befragt, das Ergebnis landet in der Variablen $RET.

Wie gesagt, diese Befragung findet noch vor der Installation des Pakets statt, aber natürlich können wir zu dem späteren Zeitpunkt der Konfiguration, z.B. in dem Script 'postinst', auf die Antworten zugreifen.

Hierzu müssen wir lediglich die Routinen des Fragesystems einbinden und dann wie schon in der 'config'-Datei die Antworten abrufen.

 mcedit postinst
 # Am Anfang einbinden:
. /usr/share/debconf/confmodule
 
 ...
 
 # Antworten abrufen und verarbeiten:
 db_get delixs-refresh/cron-time
 crontime=$RET
 
 ...

Noch ein paar Hinweise:

  • Zum Testen des 'config'-scripts muss das Paket nicht unbedingt installiert werden. Man kann es i.d.R. auch 'einfach so' als root starten.
  • Die Antworten bleiben auch nach einem 'remove' unseres Pakets in der Datenbank gespeichert, vergleichbar mit den Konfigurationsdateien unter '/etc/...'. Erst bei einem 'purge' unseres Pakets sollen sie entfernt werden.

Hierzu genügt es, in unserer 'rules'-Datei aus der Zeile

 #<----->dh_installdebconf

das Kommentarzeichen zu entfernen, dann kümmert sich der Paketmanager automatisch darum.

  • Wenn die Fragen erst mal als beantwortet in der Datenbank liegen, werden sie bei einer nächsten Ausführung durch den Paketmanager (z.B. bei einem Update oder der Neuinstallation nach einem 'remove') nicht wieder angezeigt.

Um die erneute Befragung zu erzwingen, können wir in der 'config'-Datei unsere Frage vorher als 'noch nie bearbeitet' markieren:

 db_fset delixs-refresh/cron-time seen false
  • Sobald man die Routinen des Fragesystems mit '. /usr/share/debconf/confmodule' eingebunden hat, sollte man auf eigene Bildschirmausgaben und Consolen-Eingaben mit 'echo' oder 'read' verzichten, das das Fragesystem diese beiden Kanäle beansprucht. Insbesondere sollte man auf die Ausführung von daemons verzichten, da hierbei ja gerne die Ein-/Ausgabe-Deskriptoren verbogen werden. Sollte dies doch einmal notwendig sein, muss man vorher das Fragesystem mit 'db_stop' beenden.
  • Und selbstverständlich kann man auch auf Antworten aus den Fragen anderer Pakete zugreifen, z.B. ergibt
 db_get samba-common/workgroup

als '$RET'-Value den Eintrag 'SCHULE'.
Die Klartext-Datenbank aller Antworten befindet sich unter '/var/cache/debconf/config.dat'.

Weblinks

Details zur Erstellung der 'config' und 'templates' Dateien:


zurück | Hauptseite