Jak mogę zainstalować pakiety bez uruchamiania powiązanych z nimi usług?

13

Jak zapewne wiesz, domyślnie podczas instalowania pakietu w systemie opartym na Debianie lub Ubuntu, jeśli pakiet zawiera usługę, usługa ta będzie na ogół włączona i uruchomiona automatycznie podczas instalacji pakietu.

To dla mnie problem.

Odkryłem, że muszę zarządzać szablonami do budowania kontenerów LXC. Istnieje kilka kontenerów, każdy odpowiadający wydaniu Debian lub Ubuntu. (Istnieją również pojemniki na bazie Red Hat, ale nie są one tutaj istotne).

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

Czasami okaże się, że szablony mają brakujący pakiet lub potrzebuję jakiejś innej zmiany, więc chrootuję się w nich, aby zainstalować pakiet. Niestety, kiedy to robię, kończę z uruchomionymi kilkoma kopiami usługi pakietu!

Na przykład okazało się, że szablony nie mają demona syslog, więc zainstalowałem jeden:

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

I natychmiast skończyły się cztery uruchomione rsyslog. Nie wspominając o dwóch kopiach exim4. Ups!


Czytałem gdzieś (choć już nie mogę go ponownie znaleźć), że nie powinno uruchamiać usług, gdy działa w chroot, ale najwyraźniej tak się nie dzieje.

Jeden potencjalnie realny paskudny hack wymaga tymczasowego zastąpienia różnych poleceń, które faktycznie uruchamiają usługi, takich jak start-stop-daemoni initctlchociaż jest to o wiele więcej pracy, niż naprawdę chciałem zrobić. Jeśli nie mam innego wyboru ...

Idealnym rozwiązaniem byłoby, gdyby systemy oparte na Debianie przestały robić to badziewie, ale jeśli tego nie zrobi, być może niejasna lub nieudokumentowana opcja wiersza poleceń apt-get?

W przypadku, gdy nie było to jasne, naprawdę chcę zachować wszystko, co związane z zarządzaniem szablonami poza szablonami, jeśli to możliwe.

Michael Hampton
źródło

Odpowiedzi:

23

W przypadku Debiana możesz to zrobić za pomocą policy-rc.d . Oto jedno wyjaśnienie :

Skrypty opiekuna pakietu powinny komunikować się z systemem init tylko za pomocą invoke-rc.d, update-rc.d i nagłówków skryptów inicjujących LSB ... invoke-rc.d sprawdzi przed podjęciem działania, czy /usr/sbin/policy-rc.d jest wykonywalny, wywoła go z odpowiednią nazwą usługi i bieżącym numerem poziomu uruchamiania w swoim wierszu poleceń i będzie działać zgodnie z kodem wyjścia. Na przykład wartość zwracana 101 uniemożliwi podjęcie planowanego działania. Obejmuje to automatyczne uruchomienie usługi po instalacji pakietu, a także zatrzymanie usługi po usunięciu pakietu i zmniejsza rytuał stop-upgrade-restart podczas aktualizacji pakietu do samej aktualizacji, która może spowodować pozostawienie starej wersji usługi

Ponieważ nie chcesz, aby jakiekolwiek usługi się kiedykolwiek uruchamiały, skrypt policy-rc.d może być po prostu

#!/bin/sh
exit 101

Jest to technika stosowana przez narzędzia takie jak pbuilder i mockage-debootstrap Dockera .

Niestety, ta technika nie działa z chrootami Ubuntu . Pakiety, które integrują się z początkowym wywołaniem systemowym init / usr / sbin / initctl zamiast invoke-rc.d podczas instalacji i initctl nie konsultuje się z policy-rc.d. Według autora upstart obejście polega na zamianie / sbin / initctl na dowiązanie symboliczne do / bin / true w chroocie. Widać to również w mkimage-debootstrap, robią to

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl
Sciurus
źródło
Wydaje się to dość czyste, chociaż trzeba będzie je również usunąć przed utworzeniem kontenera z szablonu.
Michael Hampton
1
Dzięki za to. Mogę skończyć po prostu zdzieraniem skryptu mockage-debootstrap Dockera, ponieważ wydaje się, że głównie rozwiązali ten problem.
Michael Hampton
4

Możesz to zrobić:

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

Nie testowałem tego z chrootem, ale powinno działać. Na początku ustawia zmienną środowiskową RUNLEVEL, więc procesy zainicjowane przez apt-get nie uruchomią żadnych usług, ponieważ będą „myśleć”, że system działa w trybie pojedynczym. Ponieważ środowisko jest modyfikowane w sposób, w jaki może wpływać na przyszłe polecenia, konieczne jest zamknięcie powłoki, gdy zmodyfikowane środowisko nie jest już potrzebne, jest to realizowane przez polecenie exit na końcu. Nie mogą być pewne rzadkie (?) Pakietów, które nie zainstaluje się poprawnie w trybie pojedynczym (ale AFAIK nie powinno to być problemem w większości przypadków).

DavisNT
źródło
Czy jest export RUNLEVEL=1tu ważna część? Co dokładnie to powoduje?
Michael Hampton
@MichaelHampton Wierzę, że zmienna środowiskowa RUNLEVEL zapewni bieżący poziom uruchamiania. W tym przypadku po prostu go nadpisuje, aby każda aplikacja pomyślała, że ​​działa na 1. To rodzaj „kludge”, ale powinno wystarczyć.
WinkyWolly
Dodano wyjaśnienie do oryginalnej odpowiedzi. Zasadniczo tak powiedział @WinkyWolly.
DavisNT,
Niestety okazało rsyslogsię, że jest to jeden z „rzadkich” pakietów, które wysadziły się całkowicie podczas próby instalacji w ten sposób. Może się to jednak przydać, więc możesz zachować opinię :)
Michael Hampton