Wie kann ich Pakete installieren, ohne die zugehörigen Dienste zu starten?

13

Wie Sie wahrscheinlich wissen, wird dieser Dienst standardmäßig aktiviert und automatisch gestartet, wenn Sie ein Paket auf einem Debian- oder Ubuntu-basierten System installieren, wenn das Paket einen Dienst enthält.

Das ist ein Problem für mich.

Ich musste Vorlagen zum Erstellen von LXC-Containern verwalten. Es gibt mehrere Container, die jeweils einer Debian- oder Ubuntu-Version entsprechen. (Es gibt auch Red Hat-basierte Container, die hier jedoch nicht relevant sind.)

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

Gelegentlich stelle ich fest, dass die Vorlagen ein fehlendes Paket haben oder eine andere Änderung benötigen, sodass ich mich in sie einarbeiten werde, um das Paket zu installieren. Wenn ich das tue, werden leider mehrere Kopien des Paketdienstes ausgeführt!

Ich habe zum Beispiel festgestellt, dass die Vorlagen keinen Syslog-Daemon haben, also habe ich einen installiert:

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

Und schnell mit vier Kopien von rsyslog beendet. Ganz zu schweigen von zwei Kopien von exim4. Hoppla!


Ich habe irgendwo gelesen (obwohl ich es jetzt nicht wieder finde), dass es keine Dienste starten soll, wenn es in einer Chroot läuft, aber das passiert hier eindeutig nicht.

Ein potenziell realisierbarer böser Hack erfordert das vorübergehende Ersetzen der verschiedenen Befehle, mit denen die Dienste tatsächlich gestartet werden, z. B. start-stop-daemonund initctl, obwohl dies viel mehr Arbeit ist, als ich eigentlich wollte. Wenn ich aber keine andere Wahl habe ...

Die ideale Lösung wäre hier, wenn Debian-basierte Systeme diesen Mist nicht mehr machen, aber wenn dies nicht gelingt, vielleicht eine undurchsichtige oder undokumentierte Befehlszeilenoption für apt-get?

Falls es nicht klar war, möchte ich alles, was mit der Verwaltung der Vorlagen zu tun hat, nach Möglichkeit außerhalb der Vorlagen belassen.

Michael Hampton
quelle

Antworten:

23

Für Debian können Sie dies mit policy-rc.d tun . Hier ist eine Erklärung :

Die Betreuer-Skripte eines Pakets dürfen nur über die Skript-Header invoke-rc.d, update-rc.d und LSB init mit dem Init-System kommunizieren /usr/sbin/policy-rc.d ist ausführbar, ruft es mit dem entsprechenden Dienstnamen und der aktuellen Runlevel-Nummer in der Befehlszeile auf und handelt entsprechend dem Exit-Code. Ein Rückgabewert von 101 verhindert beispielsweise, dass die geplante Aktion ausgeführt wird. Dies umfasst den automatischen Start des Dienstes bei der Paketinstallation sowie das Beenden des Dienstes beim Entfernen des Pakets und reduziert das Stop-Upgrade-Restart-Ritual bei Paket-Upgrades auf die Ausführung des Upgrades, bei dem möglicherweise die alte Version des Dienstes ausgeführt wird

Da Sie nicht möchten, dass Dienste jemals gestartet werden, kann Ihr policy-rc.d-Skript einfach sein

#!/bin/sh
exit 101

Dies ist die Technik, die von Tools wie pbuilder und Dockers mkimage-debootstrap verwendet wird .

Leider funktioniert diese Technik nicht mit Ubuntu- Chroots. Pakete, die mit dem Systemstart-Systemaufruf / usr / sbin / initctl integriert werden, rufen während der Installation nicht -rc.d auf, und initctl konsultiert nicht policy-rc.d. Laut dem Autor von upstart besteht die Problemumgehung darin, in einer Chroot / sbin / initctl durch einen Symlink zu / bin / true zu ersetzen. Sie können dies auch in mkimage-debootstrap sehen, sie tun es

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl
Sciurus
quelle
Dies scheint ziemlich sauber zu sein, aber es muss auch entfernt werden, bevor ein Container aus der Vorlage erstellt wird.
Michael Hampton
1
Danke dafür. Möglicherweise muss ich Dockers mkimage-debootstrap-Skript einfach abreißen, da sie dieses Problem anscheinend größtenteils gelöst haben.
Michael Hampton
4

Du kannst tun:

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

Ich habe es nicht mit Chroot getestet, aber es sollte funktionieren. Zuerst wird die Umgebungsvariable RUNLEVEL gesetzt, sodass von apt-get initiierte Prozesse keine Dienste starten , da sie annehmen, dass das System im Einzelmodus ausgeführt wird. Da die Umgebung so geändert wird, wie es sich auf zukünftige Befehle auswirkt, muss die Shell beendet werden, wenn die geänderte Umgebung nicht mehr benötigt wird. Dies erfolgt durch den Befehl exit am Ende. Es kann sein , einige (selten?) Pakete , die nicht richtig im Single - Modus installiert werden sollen (aber AFAIK sollte dies in den meisten Fällen nicht Problem sein).

DavisNT
quelle
Ist export RUNLEVEL=1der wichtige Teil hier? Was genau bewirkt das?
Michael Hampton
@MichaelHampton Ich glaube, die Umgebungsvariable RUNLEVEL liefert den aktuellen Runlevel. In diesem Fall überschreibt er es einfach, sodass jede Anwendung denkt, dass es auf 1 läuft. Es ist eine Art "Kludge", sollte aber ausreichen.
WinkyWolly
Erklärung zur ursprünglichen Antwort hinzugefügt. Grundsätzlich ist es das, was @WinkyWolly gesagt hat.
DavisNT
Leider war rsysloges eines der "seltenen" Pakete, die beim Versuch, auf diese Weise zu installieren, völlig in die Luft gejagt sind. Dies kann dennoch nützlich sein, sodass Sie die positive Bewertung behalten können :)
Michael Hampton