Die folgenden Anweisungen sind für die Arbeit mit CentOS 7 konzipiert, sollten jedoch problemlos auf jede Distribution übertragbar sein, die systemd ausführt. Alle Befehle werden als root ausgeführt.
Stellen Sie sicher, dass sich das System in einem stabilen Zustand befindet
Stellen Sie sicher, dass niemand anderes es benutzt und nichts anderes Wichtiges vor sich geht. Es ist wahrscheinlich eine gute Idee, Service-Providing-Einheiten wie httpd oder ftpd zu stoppen, um sicherzustellen, dass externe Verbindungen die Dinge in der Mitte nicht stören.
systemctl stop httpd
systemctl stop nfs-server
# and so on....
Hängen Sie alle nicht verwendeten Dateisysteme aus
umount -a
Hiermit wird eine Reihe von Warnungen ausgegeben, dass das Ziel beschäftigt ist, und zwar für das Root-Volume selbst und für verschiedene temporäre / System-FSs. Diese können vorerst ignoriert werden. Wichtig ist, dass außer dem Root-Dateisystem keine Dateisysteme auf der Festplatte gemountet bleiben. Überprüfen Sie dies:
# mount alone provides the info, but column makes it possible to read
mount | column -t
Wenn Sie feststellen, dass noch Dateisysteme auf der Festplatte eingehängt sind, wird noch etwas ausgeführt, das nicht ausgeführt werden sollte. Überprüfen Sie, was es verwendet fuser
:
# if necessary:
yum install psmisc
# then:
fuser -vm <mountpoint>
systemctl stop <whatever>
umount -a
# repeat as required...
Machen Sie die temporäre Wurzel
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/
Dies schafft ein sehr minimales Root-System, das (unter anderem) die Anzeige von Manpages (nein /usr/share
), Anpassungen auf Benutzerebene (nein /root
oder /home
) und so weiter unterbricht. Dies ist beabsichtigt, da es eine Ermutigung darstellt, nicht länger als nötig in einem solchen von Geschworenen manipulierten Wurzelsystem zu bleiben.
An dieser Stelle sollten Sie auch sicherstellen, dass die gesamte erforderliche Software installiert ist, da dies den Paketmanager sicher zum Erliegen bringt. Sehen Sie sich alle Schritte durch und stellen Sie sicher, dass Sie über die erforderlichen ausführbaren Dateien verfügen.
Pivot in die Wurzel
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 bewirkt, dass Bereitstellungen standardmäßig die Freigabe von Teilstrukturen zulassen (wie bei mount --make-shared
), und dies schlägt pivot_root
fehl. Daher schalten wir dies global mit ab mount --make-rprivate /
. System- und temporäre Dateisysteme werden vollständig in das neue Stammverzeichnis verschoben. Dies ist notwendig, damit es überhaupt funktioniert. Die Sockets für die Kommunikation mit systemd befinden sich unter anderem in diesem Ordner, /run
sodass laufende Prozesse nicht geschlossen werden können.
Stellen Sie sicher, dass der Remotezugriff die Umstellung überstanden hat
systemctl restart sshd
systemctl status sshd
Stellen Sie nach dem Neustart von sshd sicher, dass Sie einsteigen können, indem Sie ein anderes Terminal öffnen und sich erneut über ssh mit dem Computer verbinden. Wenn Sie das nicht können, beheben Sie das Problem, bevor Sie fortfahren.
Sobald Sie überprüft haben, dass Sie wieder eine Verbindung herstellen können, beenden Sie die aktuell verwendete Shell und stellen Sie die Verbindung wieder her. Dies ermöglicht das sshd
Verlassen der verbleibenden Gabel und stellt sicher, dass die neue Gabel nicht hält /oldroot
.
Schließe alles mit der alten Wurzel
fuser -vm /oldroot
Dadurch wird eine Liste der Prozesse gedruckt, die sich noch im alten Stammverzeichnis befinden. Auf meinem System sah es so aus:
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
Sie müssen sich mit jedem dieser Prozesse befassen, bevor Sie die Bereitstellung aufheben können /oldroot
. Der Brute-Force-Ansatz ist einfach kill $PID
für jeden, aber dies kann die Dinge zerbrechen. Um es sanfter zu machen:
systemctl | grep running
Dadurch wird eine Liste der ausgeführten Dienste erstellt. Sie sollten in der Lage sein, dies mit der Liste der Prozesse zu korrelieren, die gehalten werden, /oldroot
und diese dann systemctl restart
für jeden von ihnen ausgeben . Einige Dienste lehnen es ab, im temporären Stammverzeichnis aufzurufen und in einen fehlerhaften Status zu wechseln. diese sind für den Moment nicht wirklich wichtig.
Wenn es sich bei dem Root-Laufwerk, dessen Größe Sie ändern möchten, um ein LVM-Laufwerk handelt, müssen Sie möglicherweise auch einige andere ausgeführte Dienste neu starten, auch wenn sie nicht in der von erstellten Liste angezeigt werden fuser -vm /oldroot
. Wenn Sie feststellen, dass Sie die Größe eines LVM-Laufwerks unter Schritt 7 nicht ändern können, versuchen Sie es systemctl restart systemd-udevd
.
Einige Vorgänge lassen sich nicht einfach abwickeln systemctl restart
. Für mich gehörten diese dazu auditd
(die nicht gerne über getötet werden systemctl
, und wollten also nur ein kill -15
). Diese können individuell behandelt werden.
Der letzte Prozess, den Sie normalerweise finden, ist systemd
selbst. Führen Sie dazu systemctl daemon-reexec
.
Sobald Sie fertig sind, sollte die Tabelle folgendermaßen aussehen:
USER PID ACCESS COMMAND
/oldroot: root kernel mount /oldroot
Hänge die alte Wurzel ab
umount /oldroot
An dieser Stelle können Sie alle erforderlichen Manipulationen durchführen. Die ursprüngliche Frage erforderte einen einfachen resize2fs
Aufruf, aber Sie können hier tun, was Sie wollen. Ein weiterer Anwendungsfall ist die Übertragung des Root-Dateisystems von einer einfachen Partition nach LVM / RAID / whatever.
Drehen Sie die Wurzel zurück
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
Dies ist eine einfache Umkehrung von Schritt 4.
Entsorgen Sie die temporäre Wurzel
Wiederholen Sie die Schritte 5 und 6, außer wenn Sie /tmp/tmproot
anstelle von verwenden /oldroot
. Dann:
umount /tmp/tmproot
rmdir /tmp/tmproot
Da es ein tmpfs ist, löst sich die temporäre Wurzel an diesem Punkt im Äther auf, um nie wieder gesehen zu werden.
Bringen Sie die Dinge wieder an ihren Platz
Hängen Sie die Dateisysteme erneut ein:
mount -a
Zu diesem Zeitpunkt sollten Sie auch die in Schritt 7 vorgenommenen Anpassungen aktualisieren /etc/fstab
und diesen grub.cfg
entsprechend anpassen.
Starten Sie alle fehlgeschlagenen Dienste neu:
systemctl | grep failed
systemctl restart <whatever>
Freigegebene Teilbäume wieder zulassen:
mount --make-rshared /
Starten Sie die gestoppten Service Units - Sie können diesen einzelnen Befehl verwenden:
systemctl isolate default.target
Und du bist fertig.
Vielen Dank an Andrew Wood, der diese Entwicklung auf RHEL4 ausgearbeitet hat, und Steve, der mir die Verbindung zu ersteren zur Verfügung gestellt hat.