So, nun noch einmal etwas ausführlicher: Ich habe zuerst die Jails heruntergefahren und alle sonstigen Dienste beendet. Außerdem habe ich die Jails aus der rc.conf genommen und in ihre Partionen in der fstab auskommentiert. Dann Reboot in den Single User Mode. Dort zuerst jede der System-Partionen mit fsck(8) behandeln und anschließen per dump(8) gesichert. Dabei habe ich einige sehr große Dateien, die ich eh nochmal im Offline-Backup habe und die nicht lebenswichtig sind, per "nodump"-Flag ausgeschlossen.
Danach mit "mount -a" alle Partitionen eingehängt. Den neuen Kernel und die neue Welt hatte ich bereits zuvor gebaut und nur auf den Server kopiert. Die 8 Opteron-Kerne sind zwar nicht langsam, aber mein Desktop ist doch deutlich schneller und vor allem läuft er nicht mit Apache um die Wette. Also:
Code:
cd /usr/home/build/10.1/src
setenv MAKEOBJDIRPREFIX /usr/home/build/10.1/src
Die Umgebungsvariable sagt ihm, wo er seine Objekte findet. Leider ist der Pfad zu den Sourcen noch immer im Objekt-Verzeichnis vernudelt und kann auch nicht ohne weiteres geändert werden, weshalb man die Sourcen auf der Quell- und der Zielmaschine im gleichen Verzeichnis haben muss. Oder sich zumindest etwas mit Nullfs basteln. Dann versucht den Kernel mit "make installkernel" zu installieren. Ich ging davon aus, dass es abbrechen würde und tatsächlich tat es das. Daher war der gute, alte Make-Trick notwendig:
Code:
cp /usr/bin/make /root/make
cp /usr/home/build/10.1/obj/usr/home/build/10.1/src/usr.bin/bmake/make /usr/bin/make
Da /usr/bin/make statisch gelinkt ist und so gut wie keine Syscalls nutzt, kann der alte Kernel mit sehr hoher Wahrscheinlichkeit das neue Binary ausführen. Da die Installation von Kernel und Welt ausschließlich das make-Kommando vom Host nutzen (alles andere wird aus der neuen Welt genommen), kann man so Inkompatibilitäten zwischen einem zu alten make(1) auf dem Host und zu neuen Makefiles in den Sourcen umgehen. Beim Bauen klappt es leider nicht, da sie in der ersten Phase wesentlich mehr Tools des Hosts nutzen.
Zumindest war am Ende der Kernel problemlos installiert und ich konnte das System ein zweites Mal rebooten. Nun passierte genau das, was ich bereits befürchtet hatte. FreeBSD 10.1 weigert sich aufgrund des gmirror die Partitionen zu lesen und kann folglich kein Rootdateisystem mounten:
Code:
GEOM_PART: integrity check failed (mirror/gm0, MBR)
Ich entschloss es erst einmal mit der Trickkiste zu probieren, bevor ich eine Live-CD über die IPMI-Karte nudel und neu partitioniere. Dafür also Reset und im Loader zum Prompt gewechselt. Dort dann die Integritätsprüfungen abgeschaltet. Das lief jahrelang, sie sind nur ein Ergebnis eines strikteren Parsers. Also nicht gefährlich:
Code:
set kern.geom.part.check_integrity="0"
Und tatsächlich bootet er dann wieder in den Single User Mode durch. Eine kurze Analyse ergab, dass die MBR-Tabellen und das darin liegende BSDLabel den einen Sektor zu lang sind, den gmirror für seine Metadaten nutzt. Sie gingen also über die ganze Platte, der gmirror war aber einen Sektor kleiner. Dadurch erkannte der Kernel eine Inkonsistenz und um mich schützen weigerte er sich. Das lässt sich aber relativ simpel reparieren. Dazu beginnt man mit einem Dump des BSDLabel:
Code:
gpart backup mirror/gm0s1 > bsdlabel_dump
Nun öffnet man die Datei in einem Editor und macht die letzte Partition einfach einen Sektor kleiner. Anschließend schreibt man das BSDLabel mit Gewalt neu:
Code:
gpart restore -F mirror/gm0s1 < bsdlabel_dump
Das gleiche wird mit dem umgebenden MBR wiederholt. Anschließend noch ein Reboot um sicherzustellen, dass die Inkonsistenz behoben ist. Danach weiter mit dem Installieren der Welt:
Code:
cd /usr/home/build/10.1/src
setenv MAKEOBJDIRPREFIX /usr/home/build/10.1/src
mergemaster -m /usr/home/build/10.1/src -UFi
make installworld
make installworld
Zweimal, da der Sprung FreeBSD 8.4 -> 10.1 offiziell nicht unterstützt wird und man nie weiß, ob im ersten Durchlauf nicht dich irgendwo mal auf den Host zurückgegriffen wurde und Dinge unbemerkt schief gegangen sind. Paranoid, ich weiß. Aber die 2 Minuten mehr brauche ich für meinen Seelenfrieden. Nun noch ein Mergemaster:
Code:
mergemaster -m /usr/home/build/10.1/src -UFi
etcupdate extract
Das "etcupdate extract" ist für das nächste Mal. Denn Mergemaster ist ein wirklich dummes Tool. Ich hatte mal wieder gleich mehrmals das Problem, dass er mir die Originalzeile zusammen mit weiteren Upstream-Änderungen als Ersatz für meine Zeile anbot, die ich aber gern behalten wollte. Also nichts neues unter der Sonne. Noch schnell die alten Dateien und Bibliotheken abgeräumt und ein weiterer Reboot in den Multi User Mode:
Code:
yes | make delete-old
yes | make delete-old-libs
Wieder per SSH auf der Kiste habe ich zuerst /etc/ durchgeschaut. Meine von Mergemaster zerkloppten Dateien repariert, die rc.conf aufgeräumt und die sysctl.conf einmal durchgegangen. Dann erstmal mein universelles Aufräumkommando, was diverse Sicherheitskopien von "make installkernel" und "make installworld" abräumt:
Code:
rm -Rf /boot/*old /libexec/*old /etc/*old /etc/*orig
Da die Paketdatenbank nur dumm von pkg_install auf pkg konvertiert worden war, wollte ich sie gleich neu machen. Also auch hier einmal Tabula Rasa:
Code:
cp -r /usr/local/etc /root/local_etc
rm -Rf /usr/local /usr/ports /var/db/pkg/* /var/db/ports/* /var/db/portsnap/*
mkdir /usr/ports
portsnap fetch extract
pkg bootstrap
Der Rest war dann das normale Vorgehen. Die gewünschten Pakete installiert und gleich einen neuen Satz meiner Dotfiles hinterher. Die alten waren Jahre alt. Die Scripte durchgegangen, ob sie noch funktionieren und einige kleinere Anpassungen vorgenommen. Die pf.conf einmal aufgeräumt, denn da hatte sich über die Jahre etwas harmloser aber nervender Wildwuchs ergeben. Die jail.conf hatte ich schon vorher geschrieben, musste ich also nur noch einkopieren. Ich habe dann die Partitionen der Jails noch einmal mit fsck(8) gescannt, sie anschließend gemountet und die Jails wieder gestartet. Sie kamen sauber wieder hoch.
Das alles war nun lediglich das Host-System. Es folgen nun als nächstes Updates für die Jails, zumindest für MySQL und den Webserver muss es sichtbare Downtimes geben. Die kündige ich natürlich vorher an. Aber nun ist erst einmal Feierabend.