Come posso installare i pacchetti senza avviare i loro servizi associati?


13

Come probabilmente saprai, per impostazione predefinita quando installi un pacchetto su un sistema basato su Debian o Ubuntu, se il pacchetto contiene un servizio, quel servizio sarà generalmente abilitato e avviato automaticamente quando installi il pacchetto.

Questo è un problema per me

Mi sono trovato a dover gestire i modelli per la costruzione di contenitori LXC. Esistono diversi contenitori, ciascuno corrispondente a una versione di Debian o Ubuntu. (Esistono anche contenitori basati su Red Hat, ma non sono rilevanti qui.)

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

Occasionalmente scoprirò che i modelli hanno un pacchetto mancante o necessitano di qualche altra modifica, quindi li chroot per installarli. Sfortunatamente quando lo faccio, finisco con diverse copie del servizio del pacchetto in esecuzione!

A titolo di esempio, ho scoperto che i modelli non avevano un demone syslog, quindi ne ho installato uno:

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

E prontamente terminato con quattro copie di rsyslog in esecuzione. Per non parlare di due copie di exim4. Oops!


Ho letto da qualche parte (anche se non riesco a trovarlo di nuovo ora) che non si suppone che avvii i servizi quando si esegue in un chroot, ma questo chiaramente non sta accadendo qui.

Un brutto hack potenzialmente praticabile richiede la sostituzione temporanea dei vari comandi che in realtà avviano servizi, come start-stop-daemone initctl, anche se questo è molto più lavoro di quanto volessi davvero fare. Se non ho altra scelta, però ...

La soluzione ideale qui sarebbe che i sistemi basati su Debian smettessero di fare questa schifezza, ma in mancanza di ciò, forse un'opzione da riga di comando oscura o non documentata per apt-get?

Nel caso in cui non fosse chiaro, voglio davvero mantenere qualsiasi cosa legata alla gestione dei modelli al di fuori dei modelli, se possibile.

Risposte:


23

Per debian puoi farlo con policy-rc.d . Ecco una spiegazione :

Si suppone che gli script del manutentore di un pacchetto si interfacciano solo con il sistema init tramite invoke-rc.d, update-rc.d e le intestazioni dello script init LSB ... invoke-rc.d verificherà, prima di agire, /usr/sbin/policy-rc.d è eseguibile, lo chiamerà con il rispettivo nome di servizio e l'attuale numero di runlevel sulla sua riga di comando e agirà in base al suo codice di uscita. Ad esempio, un valore di ritorno di 101 impedirà di intraprendere l'azione pianificata. Ciò include l'avvio automatico del servizio al momento dell'installazione del pacchetto, nonché l'arresto del servizio durante la rimozione del pacchetto e riduce il rituale di arresto-aggiornamento-riavvio durante gli aggiornamenti del pacchetto per eseguire semplicemente l'aggiornamento che potrebbe lasciare in esecuzione la vecchia versione del servizio

Dal momento che non si desidera avviare alcun servizio, lo script policy-rc.d può essere semplicemente

#!/bin/sh
exit 101

Questa è la tecnica utilizzata da strumenti come pbuilder e Docker mkimage-debootstrap .

Sfortunatamente, questa tecnica non funziona con i chroot di Ubuntu . I pacchetti che si integrano con upstart init chiamano / usr / sbin / initctl invece di invoke-rc.d durante l'installazione e initctl non consulta policy-rc.d. Secondo l'autore upstart, la soluzione alternativa è sostituire / sbin / initctl con un link simbolico a / bin / true in un chroot. Puoi vederlo anche in mkimage-debootstrap, lo fanno

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl

Sembra abbastanza pulito, anche se dovrà essere rimosso prima di creare un contenitore dal modello.
Michael Hampton

1
Grazie per questo. Potrei finire solo per strappare lo script mkimage-debootstrap di Docker, poiché sembrano aver risolto principalmente questo problema.
Michael Hampton

4

Tu puoi fare:

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

Non l'ho provato con chroot, ma dovrebbe funzionare. Inizialmente imposta la variabile d'ambiente RUNLEVEL, quindi i processi avviati da apt-get non avvieranno alcun servizio, perché "penseranno" che il sistema sia in esecuzione in modalità singola. Poiché l'ambiente viene modificato in modo tale da influire sui comandi futuri, è necessario uscire dalla shell quando l'ambiente modificato non è più necessario, ciò viene realizzato dal comando exit alla fine. Ci possono essere alcuni (rari?) Pacchetti che non si installa correttamente in modalità singola (ma per quanto ne so questo problema non dovrebbe essere nella maggior parte dei casi).


La export RUNLEVEL=1parte importante è qui? Che cosa provoca esattamente?
Michael Hampton

@MichaelHampton Credo che la variabile ambientale RUNLEVEL fornirà l'attuale livello di funzionamento. In questo caso lo sta solo sovrascrivendo, quindi qualsiasi applicazione penserà che sia in esecuzione su 1. È una specie di "kludge" ma dovrebbe bastare.
WinkyWolly,

Aggiunta spiegazione alla risposta originale. Fondamentalmente questo è ciò che ha detto @WinkyWolly.
DavisNT,

Sfortunatamente è rsyslogcapitato di essere uno dei pacchetti "rari" che è esploso completamente quando si è tentato di installare in questo modo. Questo può essere comunque utile, quindi puoi mantenere il voto :)
Michael Hampton
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.