Comment puis-je installer des packages sans démarrer leurs services associés?

13

Comme vous le savez probablement, par défaut lorsque vous installez un paquet sur un système basé sur Debian ou Ubuntu, si le paquet contient un service, ce service sera généralement activé et démarré automatiquement lorsque vous installerez le paquet.

C'est un problème pour moi.

Je me suis retrouvé à devoir gérer des modèles pour construire des conteneurs LXC. Il existe plusieurs conteneurs, chacun correspondant à une version Debian ou Ubuntu. (Il existe également des conteneurs basés sur Red Hat, mais ils ne sont pas pertinents ici.)

/var/lib/libvirt/filesystems/debian6_template
/var/lib/libvirt/filesystems/debian7_template
/var/lib/libvirt/filesystems/ubuntu1004_template
/var/lib/libvirt/filesystems/ubuntu1204_template

Parfois, je constate que les modèles ont un package manquant ou nécessitent d'autres modifications, je vais donc les chrooter pour installer le package. Malheureusement, lorsque je fais cela, je me retrouve avec plusieurs copies du service du package en cours d'exécution!

À titre d'exemple, j'ai trouvé que les modèles n'avaient pas de démon syslog, j'en ai donc installé un:

for template in /var/lib/libvirt/filesystems/{debian,ubuntu}*_template; do
    chroot $template apt-get install rsyslog
done

Et rapidement terminé avec quatre copies de rsyslog en cours d'exécution. Sans oublier deux copies d'exim4. Oups!


J'ai lu quelque part (bien que je ne puisse pas le retrouver maintenant) qu'il n'est pas censé démarrer les services lors de l'exécution dans un chroot, mais cela ne se produit clairement pas ici.

Un hack méchant potentiellement viable nécessite le remplacement temporaire des différentes commandes qui démarrent réellement les services, comme start-stop-daemonet initctl, bien que ce soit beaucoup plus de travail que je ne voulais vraiment le faire. Si je n'ai pas d'autre choix, cependant ...

La solution idéale ici serait que les systèmes basés sur Debian cessent de faire cette merde, mais à défaut, peut-être une option de ligne de commande obscure ou non documentée pour apt-get?

Au cas où ce ne serait pas clair, je veux vraiment garder tout ce qui concerne la gestion des modèles en dehors des modèles, si possible.

Michael Hampton
la source

Réponses:

23

Pour debian, vous pouvez le faire avec policy-rc.d . Voici une explication :

Les scripts de maintenance d'un paquet sont supposés n'interfacer avec le système init que par le biais des en-têtes invoke-rc.d, update-rc.d et LSB init ... invoke-rc.d vérifiera, avant d'agir, si /usr/sbin/policy-rc.d est exécutable, l'appellera avec le nom de service respectif et le numéro de niveau d'exécution actuel sur sa ligne de commande et agira selon son code de sortie. Par exemple, une valeur de retour de 101 empêchera l'exécution de l'action prévue. Cela inclut le démarrage automatisé du service lors de l'installation du package ainsi que l'arrêt du service lors de la suppression du package et réduit le rituel d'arrêt-mise à niveau-redémarrage pendant les mises à niveau du package à une simple mise à niveau qui pourrait laisser l'ancienne version du service en cours d'exécution

Comme vous ne voulez pas que les services démarrent, votre script policy-rc.d peut être simplement

#!/bin/sh
exit 101

C'est la technique utilisée par des outils comme pbuilder et Docker mkimage-debootstrap de Docker .

Malheureusement, cette technique ne fonctionne pas avec les chroots Ubuntu . Les packages qui s'intègrent à l'appel système init de démarrage / usr / sbin / initctl au lieu d'invoquer-rc.d lors de l'installation, et initctl ne consulte pas policy-rc.d. Selon l'auteur du débutant, la solution consiste à remplacer / sbin / initctl par un lien symbolique vers / bin / true dans un chroot. Vous pouvez également le voir dans mkimage-debootstrap, ils le font

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl
sciurus
la source
Cela semble assez propre, mais il faudra également le supprimer avant de créer un conteneur à partir du modèle.
Michael Hampton
1
Merci pour cela. Je vais peut-être devoir simplement arracher le script mkimage-debootstrap de Docker, car ils semblent avoir principalement résolu ce problème.
Michael Hampton
4

Tu peux faire:

export RUNLEVEL=1
for template in /var/lib/libvirt/filesystems/{debian,ubuntu}*_template; do
    chroot $template apt-get install rsyslog
done
exit

Je ne l'ai pas testé avec chroot, mais ça devrait marcher. Au début, il définit la variable d'environnement RUNLEVEL, donc les processus lancés par apt-get ne démarreront aucun service, car ils "penseront" que le système fonctionne en mode unique. Comme l'environnement est modifié de la façon dont il peut affecter les futures commandes, il est nécessaire de quitter le shell lorsque l'environnement modifié n'est plus nécessaire, ceci est accompli par la commande exit à la fin. Il peut y avoir des packages (rares?) Qui ne s'installent pas correctement en mode simple (mais AFAIK cela ne devrait pas être un problème dans la plupart des cas).

DavisNT
la source
Est-ce export RUNLEVEL=1la partie importante ici? Que fait-il exactement se produire?
Michael Hampton
@MichaelHampton Je pense que la variable d'environnement RUNLEVEL fournira le niveau d'exécution actuel. Dans ce cas, il l'écrase juste pour que toute application pense qu'il fonctionne sur 1. C'est une sorte de "kludge" mais devrait suffire.
WinkyWolly
Ajout d'explication à la réponse originale. Fondamentalement, c'est ce que @WinkyWolly a dit.
DavisNT
Malheureusement, rsyslogil s'agissait d'un des «rares» packages qui a complètement explosé lors de l'installation de cette manière. Cela peut néanmoins être utile, donc vous pouvez garder le vote positif :)
Michael Hampton