opkg ist ein Paketmanager, zugeschnitten auf die Bedürfnisse von Embedded Systemen. Die Aufgabe eines Paketmanagers ist, die auf einem System (z.B. unseren VU+ Boxen) installierte Software zu verwalten. Die Software wird dazu in Pakete gebündelt. Mit dem Paketmanager können solche Pakete installiert, deinstalliert und gelöscht werden. Der Paketmanager ermöglicht es, Software-Pakete zentral zusammenzustellen und auch zentral zu verteilen. Dafür greift der Paketmanager auf den Feed zu - das ist das zentrale Repository, in dem alle Pakete zum Download für den Paketmanager bereitgestellt werden.
Inhaltsverzeichnis
Benutzung
Für die komplette Liste der Befehle, die opkg kennt, gibt man einfach opkg
in der Shell ein.
Die wichtigsten Befehle hier auf einen Blick:
opkg update |
Akualisiert die Liste der am Feed verfügbaren Pakete |
okpg list-upgradable |
Zeigt eine Liste aller Pakete an, für die es am Feed eine Aktualisierung gibt |
opkg upgrade |
Aktualisiert alle Pakete, für die es eine neuere Version am Feed gibt |
opkg list |
Zeigt eine Liste mit allen verfügbaren Paketen an |
opkg list-installed |
Zeigt eine Liste mit allen installierten Paketen an |
opkg install <paketliste> |
Installiert ein oder mehrere Pakete |
opkg remove <paketliste> |
Deinstalliert ein oder mehrere Pakete |
Weiterführende Informationen
Für die Benutzung des Paketmanagers sind die folgenden Informationen nicht wichtig. Das wird sich vermutlich ändern, wenn man selber Pakete bauen möchte.
opkg benutzt drei Verzeichnisse für den Betrieb:
/etc/opkg/ |
Konfiguration für opkg; hier wird die Liste aller Feeds abgelegt und die Liste der benutzten Architekturen definiert. |
/var/lib/opkg/ |
Hier wird der Gesamt-Status der installierten Pakete gespeichert. Dies beinhaltet eine Liste aller Pakete, die am Feed verfügbar sind, als auch Listen mit allen Dateien, die von allen Paketen installiert wurden. |
/usr/lib/opkg/ |
Im Verzeichnis /usr/lib/opkg/alternatives/ werden Informationen zu allen Programmen verwaltet, für die es mehrere Installations-Kandidaten gibt. Ein gutes Beispiel ist busybox, welches für eine Vielzahl von Standard-Unix-Programmen eine abgespeckte Variante zur Verfügung stellt. Wenn das Original-Programm ebenfalls installiert wird, soll natürlich nicht weiter die Busybox-Variante benutzt werden.
|
Paket-Informationen
Informationen zu allen installierten Paketen legt opkg im Verzeichnis /var/lib/opkg/info/
ab. In diesem Verzeichnis befinden sich zu jedem installierten Paket mehrere Dateien:
paketname.control | Datei mit allen Meta-Informationen zum Paket paketname |
paketname.list | Liste aller vom Paket installierten Dateien |
paketname.preinst | (optional) Script, welches vor Installation von paketname ausgeführt wurde |
paketname.postinst | (optional) Script, welches nach Installation von paketname ausgeführt wurde |
paketname.prerm | (optional) Script, welches vor Deinstallation von paketname ausgeführt wird |
paketname.postrm | (optional) Script, welches nach Deinstallation von paketname ausgeführt wird |
paketname.conffiles | (optional) Liste aller vom Paket installierten Konfigurationsfiles, die beim Update nicht überschrieben werden sollen |
Eine ipk-Datei ist vom Format eine ar-Datei, die immer 3 Dateien enthält:
control.tar.gz | eine Tar-Datei mit den gerade beschriebenen Dateien aus /var/lib/opkg/info eines Paketes außer der .list-Datei
|
data.tar.gz | eine Tar-Datei mit den zu installierenden Files; dies entspricht dem Inhalt der .list-Datei |
debian-binary | enthält immer 2.0 als String |
Anmerkung: Neuere Versionen von opkg akzeptieren auch mit xz gepackte Tar-Dateien.
Mit diesen Informationen ist es einfach, zu einem installierten Paket wieder eine ipk-Datei mit einem installierbaren Paket zu bauen. Dafür kann folgendes Script benutzt werden:
#!/bin/bash name=$1 if [ ! -f "/var/lib/opkg/info/$name.control" ]; then echo "Paket " $name " ist nicht installiert" exit fi builddir=/media/hdd/build.$$ mkdir $builddir || exit 1 # control-, list- und p-Dateien ins Build-Dir kopieren pushd /var/lib/opkg/info > /dev/null for file in $name.*; do cp $file $builddir/${file#"$name."} done cd $builddir # tar-Datei mit allen gelisteten Dateien erstellen tar -czf data.tar.gz --no-recursion -T list 2>/dev/null # opkg benötigt für jedes Verzeichnis einen eigenen Eintrag, # deswegen das tar-File noch einmal aus- und wieder einpacken. mkdir clean cd clean tar -xf ../data.tar.gz tar -czf ../data.tar.gz . cd .. tar -czf control.tar.gz $(ls control conffiles pre* post* 2> /dev/null) echo "2.0" > debian-binary version=$(grep Version: control | sed -e 's/.*: *//') package=$(grep Package: control | sed -e 's/.*: *//') arch=$(grep Architecture: control | sed -e 's/.*: *//') ipk=${package}_${version}_${arch}.ipk ar r $ipk debian-binary control.tar.gz data.tar.gz 2> /dev/null popd > /dev/null mv -i $builddir/$ipk . rm -fr $builddir
Pakete selber bauen
Ein Paket ist eine Sammlung von zu installierenden Dateien, Metainformationen sowie vor und nach Installation auszuführenden Scripten. Als Paket-Container-Format wird dafür das unter Unix seit Ewigkeiten benutzte ar-Format verwendet, mit dem auch Bibliotheken für statische Libraries (.a-Files) erstellt werden.
In einer .ipk-Datei befinden sich immer drei Dateien: control.tar.gz, data.tar.gz, debian-binary. In der Datei control.tar.gz befinden sich alle Meta-Daten zum Programm:
control
(diese Datei muss enthalten sein),conffiles
(optional Datei mit einer Liste von Konfigurationsfiles, die nicht überschrieben werden sollen; pro Zeile ein Filename - wird z.B. im Paket "base-files" benutzt, siehe/var/lib/opkg/info/base-files.*
auf der Box)preinst
,prerm
(optional, Shellscripten, die vor dem installieren bzw. löschen ausgeführt werden)postinst
,postrm
(optional, Shellscripten, die nach dem installieren bzw. löschen ausgeführt werden)
Die Datei data.tar.gz beinhaltet die eigentlichen Paket-Daten, die installiert werden sollen. Die Datei data.tar.gz wird von opkg im Root-Verzeichnis ausgepackt. opkg benutzt dafür seinen eigenen Entpacker, der - im Gegensatz zu tar pingelig ist, was fehlende Verzeichnisse im Tar-File angeht.
Das control File
Bleibt noch das control-File zu erklären. Ein control-File besteht aus einer Reihe von Feld: Wert-Paaren, mit nachfolgend beschriebener Bedeutung. Dabei sind lediglich die Felder Package: und Architecture: Pflichtfelder, es ist aber sinnvoll, wenigstens noch Version: und Description: mit anzugeben.
- Package: (Pflichtfeld) ist der Paket-Name ohne die Versions-Nummer
- Architecture: (Pflichtfeld) bestimmt, unter welcher Architektur das Paket sinnvollerweise installiert werden kann. Hier nimmt man "all", wenn es unabhängig vom Prozessor ist, also z.B. ein Python-Script. Ansonsten z.B. armv7ahf-vfp-neon wenn es spezifisch für eine unserer 4k-Boxen ist, weil z.B. ein kompiliertes Binary enthalten ist. Gültige Werte für "Architecture" für deine Box stehen in der Datei /etc/opkg/arch.conf.
- Version: (empfohlenes Feld) ist die Versionsnummer des Paketes. Hier fährt man sehr gut mit einer numerischen Versionsnummer (z.B. 1.2-r0), da opkg anhand der Versionsnummer alphanumerisch sortiert und entscheidet, ob ein Paket neuer als ein bereits installiertes ist. Versionsnummern a la "gitXXX" sind eher ungeeignet.
- Description: (empfohlenes Feld) ausführliche Beschreibung des Pakets. Dieses Feld kann aus mehreren Zeilen bestehen, wobei nachfolgende Zeilen immer mit einem Leerzeichen beginnnen müssen, Absätze mit " .".
- Depends: beschreibt die Abhängigkeiten zu anderen Paketen. Diese Zeile kann eine Liste von Paketen enthalten, die installiert sein müssen bzw. installiert werden sollen, wenn das Paket installiert wird. Für jedes Paket kann weiter noch angeben werden, welche Version benötigt wird. Das kann man durch (>> Version), (>= Version), (= Version), (<= Version), (<< Version) hinter dem Paketnamen angeben. >>: neuer als, >=: mindestens, =: genau gleich, <=: höchstens, <<: älter als.
- Conflicts: wenn die Installation dieses Paketes sich mit einem anderen Paket beisst (z.B. wenn beide Pakete gleiche Files installieren), werden die Pakete durch Komma getrennt hier aufgeführt.
- Installed-Size: hier kann der vom installierten Paket in Anspruch genommene Speicherplatz in KB angegeben werden
- Maintainer: Wer betreut dieses Paket?
- Priority: extra, optional, required, standard
- Provides: Für kompliziertere Abhängigkeiten von Paketen mit virtuellen Paketen definiert "Provides:", für welches virtuelle Paket das Paket eine Installation erfüllt. Dafür kann ein Paket z.B. "Depends: vpaket" voraussetzen, und unser Paket "Package: paket" sowie "Provides: vpaket" definieren. Das macht man gerne, wenn man Pakete für spezifische Hardware schnürt, z.B. eine bestimmte Box.
- Section: Welcher Sektion das Paket zugeordnet werden soll.
- Replaces: Manchmal gibt es für ein altes Paket ein neues, welches das alte ersetzt. Um Konflikte mit gleichen Files zu verhindern, kann man hier angeben, welches alte Paket unser Paket ersetzt.
- Source: Quelle des Pakets.
- Recommends: Liste von Paketen, für die es Sinn macht, zusätzlich zu diesem Paket installiert zu werden. Quasi eine sehr weiche Depends: Klausel.
- Suggests: Liste von Paketen, für die es vielleicht Sinn macht, zusätzlich zu diesem Paket installiert zu werden - eine noch weichere Depends: Klausel.
Als Beispiele kann man sich die tausenden von *.control
im Verzeichnis /var/lib/opkg/info/
anschauen. Pro installiertes Paket steht dort die control-Datei, die mit dem Paket ausgeliefert wurde.
Ein Script um Pakete zu erstellen
Mit folgendem Script kann aus einem Installations-Verzeichnis heraus ein fertiges Paket gebaut werden. Dafür ist es nur nötig, eine fertige control-Datei und das fertige data.tar.gz im Verzeichnis abzulegen. Wenn man ein Programm fertig kompiliert hat, lässt es sich üblicherweise mit dem Kommando make install
installieren. Man kann aber bei den meisten Programmen heute make install DESTDIR=/media/hdd/install
angeben, um das Programm unter einem anderen Root-Verzeichnis, z.B. /media/hdd/install/
, zu installieren. Von hier kann man noch einmal schauen, was alles installiert würde, und von hier das data.tar.gz-File erstellen.
Das folgende Script wird im Installations-Root (z.B. /media/hdd/install/
) ausgeführt:
#!/bin/bash if [ ! -f "control" -o ! -f "data.tar.gz" ]; then echo "Verzeichnis enthält keine Paketdaten" exit fi tar -czf control.tar.gz $(ls control conffiles pre* post* 2> /dev/null) echo "2.0" > debian-binary version=$(grep Version: control | sed -e 's/.*: *//') package=$(grep Package: control | sed -e 's/.*: *//') arch=$(grep Architecture: control | sed -e 's/.*: *//') ipk=${package}_${version}_${arch}.ipk ar r $ipk debian-binary control.tar.gz data.tar.gz
Wichtig: für dieses Script wird das ar aus den Binutils benötigt, hier funktioniert das ar aus Busybox nicht. Ein Binutils-Paket für die ARM-Architektur findet sich bei uns im Downloads-Bereich, für MIPSEL wird man fündig, wenn man im Netz nach Debian-Paketen sucht.