8.2. Gestion de paquets

La gestion de paquets est un ajout souvent demandé au livre LFS. Un gestionnaire de paquets permet de conserver une trace des fichiers installés, simplifiant ainsi leur suppression ou leur mise à jour. Un gestionnaire de paquets gérera tant les fichiers binaires et de bibliothèque que l'installation des fichiers de configuration. Avant tout, NON—cette section ne parle pas d'un gestionnaire de paquets particulier, elle n'en recommande pas non plus. Elle fait un tour des techniques les plus populaires pour indiquer comment elles fonctionnent. Le parfait gestionnaire de paquets pourrait faire partie de ces techniques ou pourrait être une combinaison d'une ou plusieurs techniques. Cette section mentionne brièvement les problèmes pouvant survenir lors de la mise à jour des paquets.

Parmi les raisons de l'absence d'un gestionnaire de paquets mentionné dans LFS ou BLFS :

Des astuces ont été écrites sur le thème de la gestion de paquets. Visitez le Projet des astuces et voyez celui qui satisfait vos besoins.

8.2.1. Problèmes de mise à jour

Un gestionnaire de paquets facilite la mise à jour des nouvelles versions au moment de leur sortie. Généralement, les instructions dans les livres LFS et BLFS peuvent être utilisées pour mettre à jour vers de nouvelles versions. Voici quelques points à connaître pour une mise à jour de paquets, spécifiquement sur un système en cours de fonctionnement.

  • Si le noyau Linux doit être mis à jour (par exemple de 5.10.17 à 5.10.18 ou 5.11.1), rien d'autre n'a besoin d'être reconstruit. Le système continuera de fonctionner grâce à l'interface bien définie entre le noyau et l'espace utilisateur. En particulier, les en-têtes de l'API de Linux n'ont pas besoin d'être mises à jour (et ne devraient pas l'être, voir le point suivant) avec le noyau. Vous devrez redémarrer votre système pour utiliser le noyau à jour.

  • Si les en-têtes de l'API Linux doivent être mis à jour vers une nouvelle version, il est plus sûr de reconstruire LFS. Bien que vous pourriez être capable de ne pas reconstruire tous les paquets dans leur ordre de dépendances, nous ne vous le recommandons pas.

  • Si un paquet contenant une bibliothèque partagée est mis à jour et si le nom de cette dernière est modifié, alors les paquets liés dynamiquement à la bibliothèque devront être recompilés pour être liés à la nouvelle bibliothèque. Remarquez qu'il n'y a aucune corrélation entre la version du paquet et le nom de la bibliothèque. Par exemple, considérez un paquet foo-1.2.3 qui installe une bibliothèque partagée de nom libfoo.so.1. Disons que vous mettez à jour le paquet avec une nouvelle version foo-1.2.4 qui installe une bibliothèque partagée de nom libfoo.so.2. Dans ce cas, tous les paquets liés dynamiquement à libfoo.so.1 doivent être recompilés pour être liés à libfoo.so.2. Vous ne devez pas supprimer les anciennes bibliothèques jusqu'à ce que les paquets indépendants soient recompilés.

  • Si vous mettez à jour un paquet qui contient une bibliothèque partagée, et que le nom de la bibliothèque ne change pas, mais que le numéro de version du fichier de la bibliothèque décroît (par exemple le nom reste libfoo.so.1, mais le nom du fichier de la bibliothèque change de libfoo.so.1.25 à libfoo.so.1.24), vous devrez supprimer le fichier de bibliothèque de la version précédente (libfoo.so.1.25 dans ce cas). Sinon, en lançant ldconfig (par vous-même via la ligne de commande, ou par l'installation d'un paquet) vous réinitialiserez le lien symbolique libfoo.so.1 vers l'ancien fichier de bibliothèque parce qu'il a une version « plus récente », puisque le numéro est plus grand. Cette situation arrive quand vous installez une version précédente d'un paquet, ou que le paquet change de pratique de nommage des versions.

  • Si un paquet contenant une bibliothèque partagée est mis à jour, et que le nom de la bibliothèque ne change pas, mais qu'un problème important (en particulier une vulnérabilité de sécurité) est corrigé, tous les programmes en cours d'exécution liés à la bibliothèque partagée doivent être redémarrés. La commande suivante, lancée en root après la mise à jour, affichera ce qui utilise les anciennes versions de ces bibliothèques (remplacez libfoo par le nom de la bibliothèque) :

    grep -l  -e 'libfoo.*deleted' /proc/*/maps |
       tr -cd 0-9\\n | xargs -r ps u

    Si OpenSSH est utilisé pour accéder au système et qu'il est lié à la bibliothèque mise à jour, vous devrez redémarrer le service sshd, vous déconnecter, vous reconnecter et relancer la commande pour confirmer que plus rien n'utilise encore les bibliothèques supprimées.

  • Si un binaire ou une bibliothèque partagée est remplacé, les processus utilisant le code ou les données du binaire ou de la bibliothèque peuvent crasher. La manière correcte de mettre à jour un binaire ou une bibliothèque partagée sans causer de crash de processus est de le ou la supprimer d'abord, puis d'installer la nouvelle version. La commande install fournie par Coreutils implémente déjà cela et la plupart des paquets l'utilisent pour installer des binaires et des bibliothèques. Cela signifie que vous n'aurez pas ce problème la plupart du temps. Cependant, le processus d'installation de certains paquets (notamment Mozilla JS dans BLFS) se contentent de réécrire par dessus le fichier s'il existe déjà et cause un crash, donc il est plus prudent de sauvegarder votre travail et de fermer les processus inutiles avant de mettre à jour un paquet.

8.2.2. Techniques de gestion de paquets

Ce qui suit est une liste de techniques habituelles de gestion de paquets. Avant de prendre une décision sur un gestionnaire de paquets, faites une recherche sur les différentes techniques et notamment leurs faiblesses.

8.2.2.1. Tout est dans ma tête !

Oui, c'est une technique de gestion de paquets. Certains n'éprouvent pas le besoin d'un gestionnaire de paquets parce qu'ils connaissent très bien les paquets et connaissent les fichiers installés par chaque paquet. Certains utilisateurs n'en ont pas besoin parce qu'ils planifient la reconstruction entière de LFS lorsqu'un paquet est modifié.

8.2.2.2. Installer dans des répertoires séparés

C'est une gestion des paquets tellement simple qu'elle ne nécessite aucun paquet supplémentaire pour gérer les installations. Chaque paquet est installé dans un répertoire séparé. Par exemple, le paquet foo-1.1 est installé dans /usr/pkg/foo-1.1 et un lien symbolique est créé de /usr/pkg/foo vers /usr/pkg/foo-1.1. Lors de l'installation de la nouvelle version foo-1.2, elle est installée dans /usr/pkg/foo-1.2 et l'ancien lien symbolique est remplacé par un lien symbolique vers la nouvelle version.

Les variables d'environnement telles que PATH, LD_LIBRARY_PATH, MANPATH, INFOPATH et CPPFLAGS ont besoin d'être étendues pour inclure /usr/pkg/foo. Pour plus de quelques paquets, ce schéma devient ingérable.

8.2.2.3. Gestion de paquet par lien symbolique

C'est une variante de la technique précédente. Chaque paquet est installé de façon similaire au schéma précédent. Mais au lieu de réaliser le lien symbolique, chaque fichier dispose d'un lien symbolique vers son équivalent dans la hiérarchie /usr. Ceci supprime le besoin d'étendre les variables d'environnement. Bien que les liens symboliques peuvent être créés par l'utilisateur, pour automatiser la création, certains gestionnaires de paquets ont été écrits avec cette approche. Parmi les plus populaires se trouvent Stow, Epkg, Graft et Depot.

L'installation doit être faussée, de façon à ce que chaque paquet pense qu'il est installé dans /usr alors qu'en réalité il est installé dans la hiérarchie /usr/pkg. Installer de cette manière n'est généralement pas une tâche triviale. Par exemple, considérez que vous installez un paquet libfoo-1.1. Les instructions suivantes pourraient ne pas installer correctement le paquet :

./configure --prefix=/usr/pkg/libfoo/1.1
make
make install

L'installation fonctionnera, mais les paquets dépendants pourraient ne pas lier libfoo comme vous vous y attendriez. Si vous compilez un paquet qui se lie à /usr/pkg/libfoo/1.1/lib/libfoo.so.1 au lieu de /usr/lib/libfoo.so.1 comme vous le prévoyez. La bonne approche est d'utiliser la stratégie DESTDIR pour fausser l'installation du paquet. Cette approche fonctionne ainsi :

./configure --prefix=/usr
make
make DESTDIR=/usr/pkg/libfoo/1.1 install

La plupart des paquets prennent en charge cette approche, mais elle pose problème à certains. Pour les paquets non compatibles, vous pouvez soit les installer manuellement soit trouver plus simple d'installer les paquets problématiques dans /opt.

8.2.2.4. Basé sur le temps

Avec cette technique, un fichier est balisé avec l'heure avant l'installation du paquet. Après l'installation, une simple utilisation de la commande find avec les options appropriées peut générer une trace de tous les fichiers installés après que le fichier temps a été créé. install-log est un gestionnaire de paquets écrit avec cette approche.

Bien que ce schéma a l'avantage d'être simple, il a deux inconvénients. Si à l'installation, les fichiers sont installés sans balise de temps autre que l'heure actuelle, ces fichiers ne seront pas suivis par le gestionnaire de paquets. De plus, ce schéma peut seulement être utilisé lorsqu'un seul paquet est installé à la fois. Les traces ne sont pas fiables si deux paquets sont installés dans deux consoles différentes.

8.2.2.5. Tracer les scripts d'installation

Avec cette approche, les commandes que les scripts d'installation accomplissent sont enregistrées. Il y a deux techniques que vous pouvez utiliser :

Vous pouvez initialiser la variable d'environnement LD_PRELOAD pour qu'elle pointe vers une bibliothèque à précharger avant l'installation. Lors de l'utilisation de cette dernière, cette bibliothèque trace les paquets en cours d'installation en s'attachant eux-mêmes aux différents exécutables comme cp, install, mv et trace les appels système qui modifient le système de fichiers. Pour que cette approche fonctionne, tous les exécutables ont besoin d'être liés dynamiquement sans bit suid ou sgid. Le préchargement de la bibliothèque pourrait causer quelques effets de bord involontaires lors de l'installation ; donc, réalisez quelques tests pour vous assurer que le gestionnaire de paquets ne casse rien et trace bien tous les fichiers appropriés.

La seconde technique est d’utiliser strace, qui trace tous les appels du système faits pendant l'exécution des scripts d'installation.

8.2.2.6. Créer des archives de paquets

Dans ce schéma, l'installation d'un paquet est faussée dans un répertoire séparé comme décrit plus haut. Après l'installation, une archive du paquet est créée en utilisant les fichiers installés. L'archive est ensuite utilisée pour installer le paquet soit sur la machine locale soit même sûr d'autres machines.

Cette approche est utilisée par la plupart des gestionnaires de paquets trouvés dans les distributions commerciales. Les exemples de gestionnaires qui suivent cette approche sont RPM (qui est parfois requis par la Spécification de base de Linux Standard), pkg-utils, apt de Debian, et le système de portage de Gentoo. Une astuce décrivant comment adopter ce style de gestion de paquets pour les systèmes LFS se trouve à http://www.fr.linuxfromscratch.org/view/astuces/fakeroot-fr.txt.

La création de fichiers de paquet qui incluent des informations de dépendance est complexe et va au-delà de l'objectif de LFS.

Slackware utilise un système basé sur tar pour les archives de paquets. Ce système ne gère volontairement pas les dépendances de paquets car d'autres gestionnaires de paquets plus complexes le font. Pour des détails sur la gestion de paquets, voir http://www.slackbook.org/html/package-management.html.

8.2.2.7. Gestion basée sur les utilisateurs

Cette méthode, unique à LFS, a été décrite par Matthias Benkmann et est disponible sur le Projet des astuces. Dans cette méthode, chaque paquet est installé en tant qu'utilisateur séparé dans les emplacements standards. Les fichiers appartenant à un paquet sont facilement identifiés grâce à l'identifiant de l'utilisateur. Les avantages et inconvénients de cette approche sont trop complexes pour les décrire dans cette section. Pour plus de détails, voir l'astuce sur http://www.fr.linuxfromscratch.org/view/astuces/gestionnaire-paquets-utilisateur.txt.

8.2.3. Déployer LFS sur plusieurs systèmes

Un des avantages du système LFS est qu'il n'y a pas de fichiers dépendant de la position des fichiers sur un système de disque. Cloner la construction d'un système LFS sur un autre ordinateur avec une architecture similaire au système de base est aussi facile que l'utilisation de tar sur la partition LFS qui contient le répertoire racine (environ 250Mo décompressés pour une construction LFS de base), en copiant ce fichier via un transfert par réseau ou par CD-ROM vers le nouveau système et en le décompressant. À partir de là, vous devrez modifier quelques fichiers de configuration. Les fichiers de configuration que vous pouvez devoir mettre à jour comprennent : /etc/hosts, /etc/fstab, /etc/passwd, /etc/group, /etc/shadow, /etc/ld.so.conf, /etc/sysconfig/rc.site, /etc/sysconfig/network et /etc/sysconfig/ifconfig.eth0.

Vous pouvez construire un noyau personnalisé pour le nouveau système, selon les différences du matériel du système avec la configuration du noyau initial.

[Note]

Note

Il y a eu quelques rapports de problèmes lors de la copie entre architectures similaires mais non identiques. Par exemple, l'ensemble d'instructions pour l'architecture Intel n'est pas identique avec celle pour un processeur AMD et les versions plus récentes de certains processeurs peuvent avoir des instructions qui ne sont pas disponibles pour des versions antérieures.

Enfin, vous devez rendre le nouveau système amorçable via Section 10.4, « Utiliser GRUB pour paramétrer le processus de démarrage ».