Tengo varias particiones LVM, cada una con una instalación de Ubuntu. Ocasionalmente, quiero hacer un apt-get dist-upgrade
, para actualizar una instalación a los paquetes más recientes. Hago esto con chroot: el proceso suele ser algo como:
$ 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
[No se muestra: Yo también montar y desmontar /mnt/chroot-0/{dev,sys,proc}
como bind-montajes a lo real /dev
, /sys
y /proc
, como el dist-upgrade parece esperar que éstos estén presentes]
Sin embargo, después de actualizar a preciso, este proceso ya no funciona: el montaje final fallará porque todavía hay archivos abiertos en el /mnt/chroot-0
sistema de archivos. lsof
confirma que hay procesos con archivos abiertos en el chroot. Estos procesos se han iniciado durante la actualización dist, supongo que esto se debe a que ciertos servicios en el chroot deben reiniciarse (p. Ej., A través de service postgresql restart
) después de actualizar el paquete.
Entonces, me imagino que necesito decirle a advenedizo que detenga todos los servicios que se ejecutan dentro de este chroot. ¿Hay alguna manera de hacer esto de manera confiable?
He intentado:
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
Where initctl list
parece hacer lo correcto y solo enumera los procesos que se han iniciado en esta raíz en particular. Intenté agregar esto también, como lo sugiere 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
Sin embargo, estos no parecen atrapar todo; los procesos que han sido demonizados y han sido reparentados a PID 1 no se detienen. También he intentado:
sudo chroot /mnt/chroot-0 telinit 0
Pero en este caso, init no distingue entre las raíces separadas y apaga toda la máquina.
Entonces, ¿hay alguna forma de decirle a init que detenga todos los procesos en un chroot particular, para que pueda desmontar el sistema de archivos de manera segura? ¿Upstart tiene alguna facilidad para SIGTERM / SIGKILL todos los procesos secundarios (como se haría durante el apagado regular) dentro de un chroot?
Respuestas:
No confío en nada más que en el núcleo para mantener un estado sano aquí, por lo que no (ab) uso init para hacer este trabajo, ni cuento conmigo mismo para saber qué está montado o no (algunos paquetes puede montar sistemas de archivos adicionales, como binfmt_misc). Entonces, para el proceso de matanza, uso:
Y para desmontar chroots, uso:
Como apéndice, señalaría que abordar esto como un problema de inicio es probablemente la forma incorrecta de verlo, a menos que realmente tenga un init en el chroot y un espacio de proceso separado (es decir, en el caso de los contenedores LXC) . Con un solo init (fuera del chroot) y un espacio de proceso compartido, esto ya no es el "problema de init", sino que depende de usted encontrar los procesos que tienen el camino ofensivo, de ahí el camino de proceso anterior.
No está claro en su publicación inicial si estos son sistemas totalmente arrancables que solo está actualizando externamente (que es como lo leí), o si son chroots que usa para cosas como compilaciones de paquetes. Si es lo último, es posible que también desee una política-rc.d en su lugar (como la que dejó mk-sbuild) que solo prohíbe los trabajos de inicio que comiencen en primer lugar. Obviamente, esa no es una solución sensata si también están destinados a ser sistemas de arranque.
fuente
policy-rc.d
parece un enfoque interesante (simplemente podría eliminarlo después de interactuar con el chroot). ¿Afecta esto tanto a los trabajos/etc/rc*.d
como a los/etc/init/*.conf
estilos?Ya identificó el problema usted mismo: algunas cosas se ejecutan
service ...
durante la actualización de dist yservice
no son parte de Upstart, sino parte desysvinit
. Agregue una magia awk similarservice --status-all
para detener los servicios sysvinit que utilizó para los servicios de Upstart.fuente
sudo chroot /mnt/chroot-0 service --list-all
ysudo chroot /mnt/chroot-0 initctl list
, que informan que no hay servicios en ejecución. Sin embargo,/usr/bin/epmd
(desde erlang-base) todavía se está ejecutando.Sé que esta pregunta es bastante antigua, pero creo que es tan relevante hoy como lo fue en 2012, y espero que alguien encuentre útil este código. Escribí el código de algo que estaba haciendo, pero pensé en compartirlo.
Mi código es diferente, pero las ideas son muy similares a @infinity (de hecho, la única razón por la que ahora sé sobre / proc / * / root es por su respuesta: ¡gracias @infinity!). También agregué algunas funcionalidades adicionales geniales
Ahora harías 2 cosas para asegurarte de que Chroot se pueda desmontar:
Elimine todos los procesos que puedan estar ejecutándose en el chroot:
Elimine todos los procesos que puedan estar ejecutándose fuera del chroot, pero que interfieran con él (por ejemplo, si su chroot es / mnt / chroot y dd está escribiendo en / mnt / chroot / testfile, / mnt / chroot no se desmontará)
Nota: Ejecute todo el código como root
Además, para una versión menos compleja, reemplace KILL_PID con
kill -SIGTERM
okill -SIGKILL
fuente
jchroot : un chroot con más aislamiento.
Después de que se haya ejecutado su comando, se eliminará cualquier proceso iniciado por la ejecución de este comando, se liberará cualquier IPC, se desmontará cualquier punto de montaje. ¡Todo limpio!
Schroot aún no puede hacer esto, pero esto está planeado
Lo probé con éxito en OpenVZ VPS, que no puede usar docker o lxc.
Por favor lea el blog del autor para los detalles:
https://vincent.bernat.im/en/blog/2011-jchroot-isolation.html
fuente
schroot: tiene la función de gestión de sesiones. Cuando detiene la sesión, se eliminan todos los procesos.
https://github.com/dnschneid/crouton/blob/master/host-bin/unmount-chroot : estas secuencias de comandos eliminan todo el proceso chroot y desmontan todos los dispositivos montados.
fuente