As instruções abaixo foram criadas para funcionar com o CentOS 7, mas devem ser facilmente transferíveis para qualquer distribuição que execute o systemd. Todos os comandos são executados como raiz.
Verifique se o sistema está em um estado estável
Certifique-se de que ninguém mais está usando e nada mais importante está acontecendo. Provavelmente, é uma boa idéia interromper as unidades de fornecimento de serviços como httpd ou ftpd, apenas para garantir que as conexões externas não atrapalhem as coisas.
systemctl stop httpd
systemctl stop nfs-server
# and so on....
Desmonte todos os sistemas de arquivos não utilizados
umount -a
Isso imprimirá vários avisos de 'O destino está ocupado', para o próprio volume raiz e para vários FSs temporários / do sistema. Estes podem ser ignorados no momento. O importante é que nenhum sistema de arquivos em disco permaneça montado, exceto o próprio sistema de arquivos raiz. Verifique isto:
# mount alone provides the info, but column makes it possible to read
mount | column -t
Se você vir algum sistema de arquivos em disco ainda montado, algo ainda está em execução que não deveria estar. Verifique o que está usando fuser
:
# if necessary:
yum install psmisc
# then:
fuser -vm <mountpoint>
systemctl stop <whatever>
umount -a
# repeat as required...
Faça a raiz temporária
mkdir /tmp/tmproot
mount -t tmpfs none /tmp/tmproot
mkdir /tmp/tmproot/{proc,sys,dev,run,usr,var,tmp,oldroot}
cp -ax /{bin,etc,mnt,sbin,lib,lib64} /tmp/tmproot/
cp -ax /usr/{bin,sbin,lib,lib64} /tmp/tmproot/usr/
cp -ax /var/{account,empty,lib,local,lock,nis,opt,preserve,run,spool,tmp,yp} /tmp/tmproot/var/
Isso cria um sistema raiz muito mínimo, que interrompe (entre outras coisas) a visualização da página de manual (não /usr/share
), personalizações no nível do usuário (não /root
ou /home
) e assim por diante. Isso é intencional, uma vez que constitui um incentivo para não permanecer em um sistema radicular equipado com júri por mais tempo do que o necessário.
Nesse ponto, você também deve garantir que todo o software necessário esteja instalado, pois também quebrará o gerenciador de pacotes. Veja todas as etapas e verifique se você tem os executáveis necessários.
Gire na raiz
mount --make-rprivate / # necessary for pivot_root to work
pivot_root /tmp/tmproot /tmp/tmproot/oldroot
for i in dev proc sys run; do mount --move /oldroot/$i /$i; done
systemd faz com que as montagens permitam o compartilhamento de subárvore por padrão (como em mount --make-shared
), e isso causa pivot_root
falha. Portanto, desativamos isso globalmente com mount --make-rprivate /
. Os sistemas e sistemas de arquivos temporários são movidos por atacado para a nova raiz. Isso é necessário para fazê-lo funcionar; os soquetes para comunicação com o systemd, entre outras coisas, estão disponíveis /run
e, portanto, não há como fazer com que os processos em execução fiquem fechados.
Garantir que o acesso remoto tenha sobrevivido à transição
systemctl restart sshd
systemctl status sshd
Após reiniciar o sshd, assegure-se de poder entrar, abrindo outro terminal e conectando-o novamente à máquina via ssh. Se não conseguir, corrija o problema antes de prosseguir.
Depois de verificar, você pode se conectar novamente, saia do shell que está usando no momento e reconecte-se. Isso permite que o garfo restante sshd
saia e garante que o novo não esteja segurando /oldroot
.
Feche tudo ainda usando a raiz antiga
fuser -vm /oldroot
Isso imprimirá uma lista de processos ainda mantendo o diretório raiz antigo. No meu sistema, ficou assim:
USER PID ACCESS COMMAND
/oldroot: root kernel mount /oldroot
root 1 ...e. systemd
root 549 ...e. systemd-journal
root 563 ...e. lvmetad
root 581 f..e. systemd-udevd
root 700 F..e. auditd
root 723 ...e. NetworkManager
root 727 ...e. irqbalance
root 730 F..e. tuned
root 736 ...e. smartd
root 737 F..e. rsyslogd
root 741 ...e. abrtd
chrony 742 ...e. chronyd
root 743 ...e. abrt-watch-log
libstoragemgmt 745 ...e. lsmd
root 746 ...e. systemd-logind
dbus 747 ...e. dbus-daemon
root 753 ..ce. atd
root 754 ...e. crond
root 770 ...e. agetty
polkitd 782 ...e. polkitd
root 1682 F.ce. master
postfix 1714 ..ce. qmgr
postfix 12658 ..ce. pickup
Você precisa lidar com cada um desses processos antes de poder desmontar /oldroot
. A abordagem da força bruta é simplesmente kill $PID
para cada um, mas isso pode quebrar as coisas. Para fazer isso mais suavemente:
systemctl | grep running
Isso cria uma lista de serviços em execução. Você deve poder correlacionar isso com a lista de processos em espera /oldroot
e emitir systemctl restart
para cada um deles. Alguns serviços se recusam a aparecer na raiz temporária e entrar em um estado com falha; estes realmente não importam no momento.
Se a unidade raiz que você deseja redimensionar for uma unidade LVM, também será necessário reiniciar alguns outros serviços em execução, mesmo que eles não apareçam na lista criada por fuser -vm /oldroot
. Se você não conseguir redimensionar uma unidade LVM na Etapa 7, tente systemctl restart systemd-udevd
.
Alguns processos não podem ser tratados de maneira simples systemctl restart
. Para mim, estes incluídos auditd
(o que não gosta de ser morto via systemctl
, e só queria um kill -15
). Estes podem ser tratados individualmente.
O último processo que você encontrará, geralmente, é systemd
ele próprio. Para isso, corra systemctl daemon-reexec
.
Quando terminar, a tabela deve ficar assim:
USER PID ACCESS COMMAND
/oldroot: root kernel mount /oldroot
Desmonte a raiz antiga
umount /oldroot
Nesse ponto, você pode executar as manipulações necessárias. A pergunta original precisava de uma resize2fs
chamada simples , mas você pode fazer o que quiser aqui; outro caso de uso é transferir o sistema de arquivos raiz de uma partição simples para LVM / RAID / qualquer que seja.
Gire a raiz de volta
mount <blockdev> /oldroot
mount --make-rprivate / # again
pivot_root /oldroot /oldroot/tmp/tmproot
for i in dev proc sys run; do mount --move /tmp/tmproot/$i /$i; done
Essa é uma reversão direta da etapa 4.
Descarte a raiz temporária
Repita as etapas 5 e 6, exceto usando /tmp/tmproot
no lugar de /oldroot
. Então:
umount /tmp/tmproot
rmdir /tmp/tmproot
Como é um tmpfs, nesse ponto a raiz temporária se dissolve no éter, para nunca mais ser vista.
Coloque as coisas de volta em seus lugares
Monte os sistemas de arquivos novamente:
mount -a
Nesse ponto, você também deve atualizar /etc/fstab
e grub.cfg
de acordo com os ajustes feitos durante a etapa 7.
Reinicie quaisquer serviços com falha:
systemctl | grep failed
systemctl restart <whatever>
Permitir subárvores compartilhadas novamente:
mount --make-rshared /
Inicie as unidades de serviço paradas - você pode usar este único comando:
systemctl isolate default.target
E você terminou.
Muito obrigado a Andrew Wood, que trabalhou nessa evolução no RHEL4, e a Steve, que me forneceu o link para o primeiro.