Ich habe eine Reihe von LVM-Partitionen, die jeweils eine Ubuntu-Installation enthalten. Gelegentlich möchte ich eine apt-get dist-upgrade
, um eine Installation auf die neuesten Pakete zu aktualisieren. Ich mache das mit chroot - der Prozess ist normalerweise ungefähr so:
$ sudo mount /dev/local/chroot-0 /mnt/chroot-0
$ sudo chroot /mnt/chroot-0 sh -c 'apt-get update && apt-get dist-upgrade'
$ sudo umount /mnt/chroot-0
[Nicht gezeigt: Ich ein- und aushängen auch /mnt/chroot-0/{dev,sys,proc}
als Bind-Mounts auf die reale /dev
, /sys
und /proc
, wie die dist-upgrade scheint diese zu erwarten anwesend sein]
Nach dem Upgrade auf "exact" funktioniert dieser Vorgang jedoch nicht mehr. Die endgültige Umount-Datei schlägt fehl, da noch Dateien im /mnt/chroot-0
Dateisystem geöffnet sind . lsof
Bestätigt, dass in der Chroot Prozesse mit geöffneten Dateien vorhanden sind. Diese Prozesse wurden während des dist-Upgrades gestartet. Dies liegt vermutlich daran, dass bestimmte Dienste in der Chroot neu gestartet werden müssen (z. B. durch service postgresql restart
), nachdem das Paket aktualisiert wurde.
Ich denke also, ich muss upstart mitteilen, dass alle Dienste, die in dieser Chroot ausgeführt werden, gestoppt werden sollen. Gibt es eine Möglichkeit, dies zuverlässig zu tun?
Ich habe es versucht:
cat <<EOF | sudo chroot /mnt/chroot-0 /bin/sh
# stop 'initctl' services
initctl list | awk '/start\/running/ {print \$1}' | xargs -n1 -r initctl stop
EOF
Wo initctl list
scheint das Richtige zu tun und nur Prozesse aufzulisten, die in dieser bestimmten Wurzel gestartet wurden. Ich habe versucht, dies auch hinzuzufügen, wie von Tuminoid vorgeschlagen:
cat <<EOF | sudo chroot /mnt/chroot-0 /bin/sh
# stop 'service' services
service --status-all 2>/dev/null |
awk '/^ \[ \+ \]/ { print \$4}' |
while read s; do service \$s stop; done
EOF
Diese scheinen jedoch nicht alles zu erfassen; Prozesse, die auf PID 1 zurückgesetzt wurden, werden nicht gestoppt. Ich habe auch versucht:
sudo chroot /mnt/chroot-0 telinit 0
In diesem Fall unterscheidet init jedoch nicht zwischen den einzelnen Roots und fährt die gesamte Maschine herunter.
Gibt es eine Möglichkeit, init anzuweisen, alle Prozesse in einer bestimmten Chroot zu stoppen, damit ich das Dateisystem sicher trennen kann? Verfügt upstart über eine Möglichkeit, alle untergeordneten Prozesse (wie beim regulären Herunterfahren) innerhalb einer Chroot SIGTERM / SIGKILL zuzuweisen?
Antworten:
Ich traue nichts außer dem Kernel, um hier einen vernünftigen Zustand beizubehalten, also verwende ich init nicht (ab), um diesen Job zu erledigen, noch zähle ich darauf, dass ich wirklich weiß, was gemountet ist oder nicht (einige Pakete) kann zusätzliche Dateisysteme wie binfmt_misc mounten). Also verwende ich zum Prozessschlachten:
Und zum Ummounten von Chroots verwende ich:
Als Ergänzung möchte ich darauf hinweisen, dass es wahrscheinlich falsch ist, dies als Init-Problem zu betrachten, es sei denn, Sie haben tatsächlich ein Init in der Chroot und einen separaten Prozessraum (dh im Fall von LXC-Containern). . Mit einem einzelnen Init (außerhalb der Chroot) und einem gemeinsam genutzten Prozessbereich ist dies nicht mehr das Problem von "init", sondern es liegt ganz bei Ihnen, die Prozesse zu finden, die den fehlerhaften Pfad haben, daher der obige Prozesspfad.
Aus Ihrem ersten Beitrag geht nicht hervor, ob es sich um vollständig bootfähige Systeme handelt, die Sie nur extern aktualisieren (so lese ich es), oder ob es sich um Chroots handelt, die Sie für Dinge wie die Erstellung von Paketen verwenden. In letzterem Fall möchten Sie möglicherweise auch eine Policy-rc.d (wie die, die von mk-sbuild abgelegt wurde), die nur das Starten von Jobs von vornherein verbietet. Das ist natürlich keine vernünftige Lösung, wenn dies auch bootfähige Systeme sein sollen.
quelle
policy-rc.d
scheint ein interessanter Ansatz zu sein (ich könnte ihn einfach entfernen, nachdem ich mit der Chroot interagiert habe). Betrifft dies sowohl Jobs im/etc/rc*.d
- als auch im -/etc/init/*.conf
Stil?Sie haben das Problem bereits selbst identifiziert: Einige Dinge werden
service ...
während des dist-Upgrades ausgeführt undservice
gehören nicht zu Upstart, sondern zusysvinit
. Fügen Sie ähnliche awk-Magie hinzu, umservice --status-all
sysvinit-Dienste zu stoppen, wie Sie sie für Upstart-Dienste verwendet haben.quelle
sudo chroot /mnt/chroot-0 service --list-all
und ausgeführtsudo chroot /mnt/chroot-0 initctl list
, die beide keine laufenden Dienste melden. Allerdings/usr/bin/epmd
läuft (von erlang-base) noch.Ich weiß, dass diese Frage ziemlich alt ist, aber ich denke, sie ist heute genauso aktuell wie 2012, und hoffentlich findet jemand diesen Code nützlich. Ich schrieb den Code für etwas, was ich tat, dachte aber, ich würde ihn teilen.
Mein Code ist anders, aber die Ideen sind @infinity sehr ähnlich (der einzige Grund, warum ich jetzt über / proc / * / root Bescheid weiß, ist seine Antwort - danke @infinity!). Ich habe auch einige coole zusätzliche Funktionen hinzugefügt
Jetzt würden Sie zwei Dinge tun, um sicherzustellen, dass die Chroot entfernt werden kann:
Beenden Sie alle Prozesse, die möglicherweise in der Chroot ausgeführt werden:
Beenden Sie alle Prozesse, die möglicherweise außerhalb der Chroot ausgeführt werden, diese jedoch beeinträchtigen (Beispiel: Wenn Ihre Chroot / mnt / chroot ist und dd in / mnt / chroot / testfile schreibt, schlägt das Aufheben der Bereitstellung von / mnt / chroot fehl).
Hinweis: Führen Sie den gesamten Code als root aus
Ersetzen Sie für eine weniger komplexe Version KILL_PID durch
kill -SIGTERM
oderkill -SIGKILL
quelle
jchroot : eine Chroot mit mehr Isolation.
Nachdem Ihr Befehl ausgeführt wurde, wird jeder Prozess, der durch die Ausführung dieses Befehls gestartet wurde, abgebrochen, alle IPCs werden freigegeben, alle Bereitstellungspunkte werden deaktiviert. Alles sauber!
schroot kann das noch nicht, aber das ist geplant
Ich habe es erfolgreich in OpenVZ VPS getestet, das Docker oder LXC nicht verwenden kann.
Bitte lesen Sie den Blog des Autors für die Details:
https://vincent.bernat.im/en/blog/2011-jchroot-isolation.html
quelle
schroot: Es hat die Funktion der Sitzungsverwaltung. Wenn Sie die Sitzung beenden, werden alle Prozesse abgebrochen.
https://github.com/dnschneid/crouton/blob/master/host-bin/unmount-chroot : Dieses Skript beendet den gesamten Chroot-Prozess und hebt die Bereitstellung aller bereitgestellten Geräte auf.
quelle