J'ai un certain nombre de partitions LVM, chacune contenant une installation Ubuntu. Parfois, je souhaite faire une apt-get dist-upgrade
mise à jour d'une installation vers les packages les plus récents. Je le fais avec chroot - le processus est généralement quelque chose comme:
$ 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
[non illustré: je monte et démonte également en tant que fixations /mnt/chroot-0/{dev,sys,proc}
de liaison au réel /dev
, /sys
et /proc
, comme la mise à niveau dist semble s'attendre à ce qu'elles soient présentes]
Cependant, après une mise à niveau précise, ce processus ne fonctionne plus - le umount final échouera car il y a encore des fichiers ouverts sur le /mnt/chroot-0
système de fichiers. lsof
confirme qu'il existe des processus avec des fichiers ouverts dans le chroot. Ces processus ont été lancés pendant la mise à niveau dist, je suppose que c'est parce que certains services dans le chroot doivent être redémarrés (par exemple, via service postgresql restart
) après la mise à niveau du package.
Donc, je pense que je dois dire à upstart d'arrêter tous les services qui s'exécutent dans ce chroot. Existe-t-il un moyen de le faire de manière fiable?
J'ai essayé:
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
Où initctl list
semble faire la bonne chose et ne lister que les processus qui ont été démarrés dans cette racine particulière. J'ai essayé d'ajouter cela aussi, comme suggéré par Tuminoid:
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
Cependant, ceux-ci ne semblent pas tout attraper; les processus démonifiés et reparents au PID 1 ne sont pas arrêtés. J'ai aussi essayé:
sudo chroot /mnt/chroot-0 telinit 0
Mais dans ce cas, init ne fait pas de distinction entre les racines séparées et arrête la machine entière.
Alors, existe-t-il un moyen de dire à init d'arrêter tous les processus dans un chroot particulier, afin que je puisse démonter le système de fichiers en toute sécurité? L'arrivée a-t-elle la possibilité de SIGTERM / SIGKILL tous les processus enfants (comme ce serait le cas lors d'un arrêt normal) dans un chroot?
Réponses:
Je ne fais confiance à rien d'autre qu'au noyau pour garder un état sain ici, donc je n'utilise pas (ab) init pour faire ce travail, et je ne compte pas non plus sur moi-même sachant réellement ce qui est ou n'est pas monté (certains paquets peut monter des systèmes de fichiers supplémentaires, comme binfmt_misc). Donc, pour l'abattage de processus, j'utilise:
Et pour démonter les chroots, j'utilise:
En guise d'addendum, je voudrais souligner que considérer cela comme un problème d'initialisation est probablement la mauvaise façon de le voir, sauf si vous avez réellement un init dans le chroot et un espace de processus séparé (c'est-à-dire: dans le cas des conteneurs LXC) . Avec un seul init (en dehors du chroot) et un espace de processus partagé, ce n'est plus le "problème d'init", mais juste à vous de trouver les processus qui se trouvent avoir le chemin incriminé, d'où le processus ci-dessus.
Il ne ressort pas clairement de votre message initial s'il s'agit de systèmes entièrement amorçables que vous mettez à niveau uniquement en externe (c'est ainsi que je les lis), ou s'ils sont des chroots que vous utilisez pour des choses comme les builds de packages. Si c'est le dernier, vous voudrez peut-être aussi une politique-rc.d en place (comme celle déposée par mk-sbuild) qui interdit simplement le démarrage des travaux d'initialisation en premier lieu. Évidemment, ce n'est pas une solution sensée s'il s'agit également de systèmes amorçables.
la source
policy-rc.d
ressemble à une approche intéressante (je pourrais simplement le supprimer après avoir interagi avec le chroot). Cela affecte-t-il les emplois à la fois/etc/rc*.d
- et de/etc/init/*.conf
style?Vous avez déjà identifié le problème vous-même: certaines choses fonctionnent
service ...
pendant la mise à niveau dist etservice
ne font pas partie d'Upstart, mais en font partiesysvinit
. Ajoutez une magie awk similaireservice --status-all
pour arrêter les services sysvinit comme vous l'avez utilisé pour les services Upstart.la source
sudo chroot /mnt/chroot-0 service --list-all
etsudo chroot /mnt/chroot-0 initctl list
, qui ne signalent aucun service en cours d'exécution. Cependant,/usr/bin/epmd
(depuis erlang-base) est toujours en cours d'exécution.Je sais que cette question est assez ancienne, mais je pense qu'elle est aussi pertinente aujourd'hui qu'elle l'était en 2012, et j'espère que quelqu'un trouvera ce code utile. J'ai écrit le code de quelque chose que je faisais, mais j'ai pensé le partager.
Mon code est différent, mais les idées sont très similaires à @infinity (en fait - la seule raison pour laquelle je connais maintenant / proc / * / root est à cause de sa réponse - merci @infinity!). J'ai également ajouté quelques fonctionnalités supplémentaires intéressantes
Maintenant, vous feriez 2 choses pour vous assurer que le chroot peut être démonté:
Tuez tous les processus qui peuvent s'exécuter dans le chroot:
Tuez tous les processus qui peuvent s'exécuter en dehors du chroot, mais en interférant avec lui (ex: si votre chroot est / mnt / chroot et que dd écrit dans / mnt / chroot / testfile, / mnt / chroot ne pourra pas être démonté)
Remarque: exécutez tout le code en tant que root
De plus, pour une version moins complexe, remplacez KILL_PID par
kill -SIGTERM
oukill -SIGKILL
la source
jchroot : un chroot avec plus d'isolement.
Une fois votre commande exécutée, tout processus démarré par l'exécution de cette commande sera tué, tout IPC sera libéré, tout point de montage sera démonté. Tout propre!
schroot n'est pas encore en mesure de le faire, mais cela est prévu
Je l'ai testé avec succès dans OpenVZ VPS, qui ne peut pas utiliser docker ou lxc.
Veuillez lire le blog de l'auteur pour les détails:
https://vincent.bernat.im/en/blog/2011-jchroot-isolation.html
la source
schroot: Il a la fonction de gestion de session. Lorsque vous arrêtez la session, tous ses processus sont supprimés.
https://github.com/dnschneid/crouton/blob/master/host-bin/unmount-chroot : ces scripts tuent tout le processus chroot et démontent tous les périphériques montés.
la source