Les instructions ci-dessous sont conçues pour fonctionner avec CentOS 7, mais elles doivent être facilement transférables à toute distribution exécutant systemd. Toutes les commandes sont exécutées en tant que root.
S'assurer que le système est dans un état stable
Assurez-vous que personne ne l'utilise et que rien d'autre n'est important. C'est probablement une bonne idée d'arrêter les unités fournissant des services comme httpd ou ftpd, juste pour s'assurer que les connexions externes ne perturbent pas les choses au milieu.
systemctl stop httpd
systemctl stop nfs-server
# and so on....
Démontez tous les systèmes de fichiers inutilisés
umount -a
Cela imprimera un certain nombre d'avertissements «La cible est occupée», pour le volume racine lui-même et pour différents systèmes de sécurité temporaires / système. Ceux-ci peuvent être ignorés pour le moment. L'important est qu'aucun système de fichiers sur disque ne reste monté, à l'exception du système de fichiers racine lui-même. Vérifiez ceci:
# mount alone provides the info, but column makes it possible to read
mount | column -t
Si vous voyez des systèmes de fichiers sur disque toujours montés, quelque chose ne fonctionne toujours pas. Vérifiez ce qu'il utilise fuser
:
# if necessary:
yum install psmisc
# then:
fuser -vm <mountpoint>
systemctl stop <whatever>
umount -a
# repeat as required...
Faire la racine temporaire
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/
Cela crée un système racine très minimal, qui interrompt (entre autres choses) l'affichage de la page de manuel (non /usr/share
), les personnalisations au niveau de l'utilisateur (non /root
ou /home
) et ainsi de suite. Cela est intentionnel, car cela constitue un encouragement à ne pas rester plus longtemps que nécessaire dans un système racinaire truqué par un jury.
À ce stade, vous devez également vous assurer que tous les logiciels nécessaires sont installés, car cela endommagera également le gestionnaire de paquets. Parcourez toutes les étapes et assurez-vous de disposer des exécutables nécessaires.
Pivoter dans la racine
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 force les montages à autoriser le partage des sous-arbres par défaut (comme avec mount --make-shared
), et cela entraîne l' pivot_root
échec. Par conséquent, nous désactivons cela globalement avec mount --make-rprivate /
. Les systèmes de fichiers système et temporaires sont déplacés en gros vers la nouvelle racine. Ceci est nécessaire pour que cela fonctionne du tout; les sockets pour la communication avec systemd, entre autres choses, résident dans /run
, et il n’ya donc aucun moyen de faire en sorte que les processus en cours la ferment.
S'assurer que l'accès à distance a survécu au basculement
systemctl restart sshd
systemctl status sshd
Après avoir redémarré sshd, assurez-vous que vous pouvez y entrer en ouvrant un autre terminal et en vous reconnectant à la machine via ssh. Si vous ne pouvez pas, résolvez le problème avant de continuer.
Une fois que vous avez vérifié, vous pouvez vous reconnecter, quittez le shell que vous utilisez actuellement et reconnectez-vous. Cela permet aux fourchettes restantes sshd
de sortir et garantit que la nouvelle ne tient pas /oldroot
.
Fermez tout en utilisant l'ancienne racine
fuser -vm /oldroot
Ceci imprimera une liste des processus restant dans l'ancien répertoire racine. Sur mon système, cela ressemblait à ceci:
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
Vous devez gérer chacun de ces processus avant de pouvoir démonter /oldroot
. L'approche par la force brute est simplement kill $PID
pour chacun, mais cela peut casser des choses. Pour le faire plus doucement:
systemctl | grep running
Cela crée une liste de services en cours d'exécution. Vous devriez pouvoir corréler cela avec la liste des processus en cours /oldroot
, puis émettre systemctl restart
pour chacun d'eux. Certains services refuseront de se placer dans la racine temporaire et entreront dans un état d'échec. cela n'a pas vraiment d'importance pour le moment.
Si le lecteur racine que vous souhaitez redimensionner est un lecteur LVM, vous devrez peut-être également redémarrer d'autres services en cours d'exécution, même s'ils n'apparaissent pas dans la liste créée par fuser -vm /oldroot
. Si vous ne parvenez pas à redimensionner un lecteur LVM à l’étape 7, essayez systemctl restart systemd-udevd
.
Certains processus ne peuvent pas être traités simplement systemctl restart
. Pour moi, ceux-ci sont inclus auditd
(qui n'aime pas être tués via systemctl
, et je voulais juste en avoir un kill -15
). Ceux-ci peuvent être traités individuellement.
Le dernier processus que vous trouverez, généralement, est systemd
lui - même. Pour cela, lancez systemctl daemon-reexec
.
Une fois que vous avez terminé, la table devrait ressembler à ceci:
USER PID ACCESS COMMAND
/oldroot: root kernel mount /oldroot
Démonter l'ancienne racine
umount /oldroot
À ce stade, vous pouvez effectuer toutes les manipulations dont vous avez besoin. La question initiale nécessitait une simple resize2fs
invocation, mais vous pouvez faire ce que vous voulez ici; un autre cas d’utilisation consiste à transférer le système de fichiers racine d’une simple partition vers LVM / RAID / peu importe.
Faire pivoter la racine
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
C’est un renversement simple de l’étape 4.
Éliminer la racine temporaire
Répétez les étapes 5 et 6, sauf /tmp/tmproot
en lieu et place de /oldroot
. Ensuite:
umount /tmp/tmproot
rmdir /tmp/tmproot
Comme il s’agit d’un tmpfs, la racine temporaire se dissout dans l’éther pour ne plus jamais être vue.
Remets les choses à leur place
Montez à nouveau les systèmes de fichiers:
mount -a
À ce stade, vous devez également mettre à jour /etc/fstab
et grub.cfg
en fonction des ajustements que vous avez effectués à l'étape 7.
Redémarrez tous les services en échec:
systemctl | grep failed
systemctl restart <whatever>
Autoriser à nouveau les sous-arbres partagés:
mount --make-rshared /
Démarrez les unités de service arrêtées - vous pouvez utiliser cette commande unique:
systemctl isolate default.target
Et tu as fini.
Un grand merci à Andrew Wood, qui a élaboré cette évolution sur RHEL4, et à steve, qui m’ont fourni le lien avec l’ancien.