Eu tenho várias partições LVM, cada uma contendo uma instalação do Ubuntu. Ocasionalmente, quero fazer um apt-get dist-upgrade
, para atualizar uma instalação para os pacotes mais recentes. Eu faço isso com chroot - o processo geralmente é 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
[Não apresentados: Eu também montar e desmontar /mnt/chroot-0/{dev,sys,proc}
como Bind-montagens para o real /dev
, /sys
e /proc
, como o dist-upgrade parece esperar que eles estejam presentes]
No entanto, após a atualização precisa, esse processo não funciona mais - a quantia final falhará porque ainda existem arquivos abertos no /mnt/chroot-0
sistema de arquivos. lsof
confirma que existem processos com arquivos abertos no chroot. Esses processos foram iniciados durante a dist-upgrade, presumo que isso ocorra porque certos serviços no chroot precisam ser reiniciados (por exemplo, através service postgresql restart
) após a atualização do pacote.
Então, acho que preciso dizer ao iniciante para interromper todos os serviços que estão sendo executados neste chroot. Existe uma maneira de fazer isso de maneira confiável?
Eu tentei:
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
Onde initctl list
parece fazer a coisa certa e listar apenas os processos que foram iniciados nessa raiz específica. Eu tentei adicionar isso também, como sugerido por 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
No entanto, isso não parece pegar tudo; processos que foram daemonizados e reparados no PID 1 não são interrompidos. Eu também tentei:
sudo chroot /mnt/chroot-0 telinit 0
Mas, neste caso, o init não faz distinção entre as raízes separadas e desliga a máquina inteira.
Então, existe alguma maneira de dizer ao init para parar todos os processos em um chroot específico, para que eu possa desmontar com segurança o sistema de arquivos? O iniciante tem algum recurso para SIGTERM / SIGKILL todos os processos filhos (como seria feito durante o desligamento regular) dentro de um chroot?
Respostas:
Eu não confio em nada além do kernel para manter um estado sadio aqui, então não ab) uso o init para concluir este trabalho, nem conto comigo mesmo sabendo o que está ou não está montado (alguns pacotes pode montar sistemas de arquivos extras, como binfmt_misc). Então, para o abate de processos, eu uso:
E para desmontar chroots, eu uso:
Como um adendo, eu apontaria que abordar isso como um problema de init provavelmente é a maneira errada de encará-lo, a menos que você tenha um init no chroot e um espaço de processo separado (por exemplo, no caso de contêineres LXC) . Com um único init (fora do chroot) e um espaço de processo compartilhado, isso não é mais um "problema do init", mas apenas com você para encontrar os processos que possuem o caminho incorreto, portanto, o procedimento acima.
Não está claro em sua postagem inicial se estes são sistemas totalmente inicializáveis que você está apenas atualizando externamente (que é como eu o leio), ou se são chroots que você usa para coisas como compilação de pacotes. Se for o último, você também pode querer um policy-rc.d (como o do mk-sbuild) que proíbe apenas os trabalhos de inicialização iniciados em primeiro lugar. Obviamente, essa não é uma solução sensata se esses também forem sistemas inicializáveis.
fonte
policy-rc.d
parece uma abordagem interessante (eu poderia simplesmente removê-lo depois de interagir com o chroot). Isso afeta os trabalhos de estilo/etc/rc*.d
e/etc/init/*.conf
estilo?Você já identificou o problema: algumas coisas são executadas
service ...
durante o dist-upgrade eservice
não fazem parte do Upstart, mas fazem partesysvinit
. Adicione mágica awk semelhanteservice --status-all
para interromper os serviços sysvinit usados para os serviços Upstart.fonte
sudo chroot /mnt/chroot-0 service --list-all
esudo chroot /mnt/chroot-0 initctl list
, que ambos relatam nenhum serviço em execução. No entanto,/usr/bin/epmd
(da erlang-base) ainda está sendo executado.Sei que essa pergunta é bastante antiga, mas acho que é tão relevante hoje quanto em 2012 e espero que alguém ache esse código útil. Eu escrevi o código para algo que estava fazendo, mas pensei em compartilhá-lo.
Meu código é diferente, mas as idéias são muito parecidas com @infinity (na verdade - a única razão pela qual eu sei agora sobre / proc / * / root é por causa de sua resposta - obrigado @infinity!). Eu também adicionei algumas funcionalidades adicionais interessantes
Agora você faria duas coisas para garantir que o chroot possa ser desmontado:
Mate todos os processos que podem estar em execução no chroot:
Mate todos os processos que podem estar em execução fora do chroot, mas interferindo nele (por exemplo: se o chroot for / mnt / chroot e o dd estiver gravando em / mnt / chroot / testfile, o / mnt / chroot falhará na desmontagem)
Nota: Execute todo o código como root
Além disso, para uma versão menos complexa, substitua KILL_PID por um
kill -SIGTERM
oukill -SIGKILL
fonte
jchroot : um chroot com mais isolamento.
Após a execução do seu comando, qualquer processo iniciado pela execução desse comando será eliminado, qualquer IPC será liberado, qualquer ponto de montagem será desmontado. Tudo limpo!
O schroot ainda não é capaz de fazer isso, mas isso está planejado
Eu testei com sucesso no OpenVZ VPS, que não pode usar o docker ou o lxc.
Por favor, leia o blog do autor para obter detalhes:
https://vincent.bernat.im/en/blog/2011-jchroot-isolation.html
fonte
schroot: Possui o recurso de gerenciamento de sessões. Quando você para a sessão, todos os seus processos são interrompidos.
https://github.com/dnschneid/crouton/blob/master/host-bin/unmount-chroot : esses scripts eliminam todo o processo chroot e desmontam todos os dispositivos montados.
fonte