chroot-Systeme von Festplatte direkt booten
Die Aufgabe ist einfach:
Es ist ein Linux-System auf einer Partition vorhanden und es soll ein weiteres auf dieser Partition z.B. im Home-Verzeichnis installiert (bzw. eine Knoppix-CD kopiert) werden. Mit chroot ja kein Problem.
Kopieren, chroot, und man kann das System verändern und z.B. bei Knoppix später wieder brennen.
Genauso kann man ein Debian-System in dieses Verzeichnis bootstrappen:
debootstrap woody ~/newroot
Gesagt getan, lief auch gut. (Mit apt-get install
Pakete installiert usw.)
Nur, dann stellt sich die Frage: Wie boote ich dieses System denn jetzt?
Normalerweise kann man ja nur ganze root-Partitionen booten, bzw. es ist vorgesehen.
Hm, Symlinks ... Nee!
Dennoch müßte es aber doch eine Lösung dafür geben, und tatsächlich:
- eine initrd (initial ramdisk)
- mount --bind & pivot_root
genügen...
Die Initial-Ramdisk dient normalerweise dazu, dass z.B. Module geladen werden (um ext3/reiserfs anzusprechen) noch bevor das Root-Dateisystem überhaupt gemountet wird.
Normalerweise reicht es dazu, die Module zu laden und den Rest der Arbeit dem Kernel zu überlassen. Nur bei ext3 würde es dann trotzdem als ext2 gemountet, da die Reihenfolge des Probieren des Kernels standardmäßig:
"rootfs, bdev, proc, sockfs, tmpfs, shm, pipefs, ext2, ramfs, msdos, vfat, iso9660, devpts, ext3, usbdevfs, usbfs, ntfs, autofs, reiserfs"
lautet. (Siehe /proc/filesystems; SuSE hat dafür mal einen ReOrder-ext3-nach-vorne-Patch geschrieben, der aber abgelehnt wurde.)
Die Möglichkeit der Wahl lautet jetzt also:
- Das Dateisystem mounten (z.B.
mount -t ext3 /dev/hda5 /mnt
) - Mit pivot_root dahin wechseln und das alte / auf /initrd verschieben (
pivot_root /mnt /mnt/initrd
) - Dem Kernel sagen, dass das Root-Dateisystem bereits gemountet ist.
Diese Methode ist übrigens von Red Hat und wird z.B. bei einer Knoppix-Installation mit knx-hdinstall auf ext3 eingesetzt.
Natürlich müssen dafür in der initrd die erforderlichen Dateien/Programme zur Verfügung stehen.
Die Idee war jetzt:
Warum nicht einfach per pivot_root
in /mnt/home/.../newroot wechseln?
Weil es nicht geht! pivot_root gibt dann immer die Meldung:
pivot_root: Device or resource busy
Die nächste Idee wäre ja, dass man dann einfach per exec chroot /mnt/home/.../newroot /sbin/init
Init aufruft.
Geht zwar, hat aber einen "klitzekleinen" Nachteil:
/ bleibt read-only, da es nicht remountet werden kann. Es kann, wenn man es vor dem chroot
read-write mountet, nicht mehr ungemountet werden (möglicher Datenverlust, unnütze Strapazierung des Journals bei ext3).
Und jetzt kommt mount --bind ins Spiel.
Wenn man mit pivot_root
nicht / auf ein Unterverzeichnis wechseln kann, vielleicht kann man es dann ja "überlisten" und mit mount --bind
einfach das Unterverzeichnis auf /mnt2 binden. Also:
mount -t ext3 /dev/hda5 /mnt mount --bind /mnt/home/.../newroot/ /mnt2
Und das Beste ist, jetzt kann man /mnt sogar unmounten, ohne dass /mnt2 verschwindet und dahin das Root-Verzeichnis wechseln.
umount /mnt pivot_root /mnt2 /mnt2/initrd
Fertig!
Das Problem ist gelöst und das jetzt gebootete System kann / remounten, unmounten usw. So, wie wenn es von einer ganz normalen Root-Partition gewesen wäre. Genialerweise kann man jetzt auch noch /dev/hda5 wieder mounten und ins "Host-System" chrooten.
Damit kann man jetzt beliebig viele gebootstrappte Systeme von Partitionen booten oder, und dies ist für die Knoppix-Remaster-Liebhaber von Vorteil, auch um ein kopiertes Knoppix wirklich booten zu können. (Knopper hat ein Sortierskript, welches nach Zugriffszeit der Dateien die Zugriffszeiten auf der CD optimiert; Nutzer von Nur-chroot-Knoppix können dies nicht nutzen, weshalb manche Derivate langsamer als das Original sind. Anderseits wollen viele keine eigene Partition für das Remastern nutzen, da es mit dem chroot so praktisch ist.)
So abschließend noch einmal die ganzen benötigten Dateien im Image:
-rwxr-xr-x 1 root root 266 2003-07-04 18:27 /mnt/linuxrc /mnt/bin: -rwsr-xr-x 1 root root 81080 2003-05-07 09:27 mount -rwsr-xr-x 1 root root 2432 2003-05-07 09:27 pivot_root /mnt/dev: brw------- 1 root root 3, 5 1998-05-05 22:32 hda5 /mnt/lib: -rwxr-xr-x 1 root root 82456 2003-05-07 09:27 ld-linux.so.2 -rwxr-xr-x 1 root root 1104072 2003-05-07 09:27 libc.so.6 /mnt/mnt: /mnt/mnt2: /mnt/modules: -rw-r--r-- 1 root root 87626 2003-04-01 23:46 ext3.o -rw-r--r-- 1 root root 74090 2003-04-01 23:46 jbd.o /mnt/proc: /mnt/static: -rwxr-xr-x 1 root root 150580 2002-07-26 14:09 ash lrwxrwxrwx 1 root root 3 2003-04-01 23:46 init -> ash -rwxr-xr-x 1 root root 412 2002-12-09 11:09 pivot_root lrwxrwxrwx 1 root root 3 2003-04-01 23:46 sh -> ash
Als Shell wurde die ash von knoppix verwendet, da diese eingebauten mount und umount hat. Mount wird trotzdem benötigt, da das bind-Feature verwendet werden soll.
Linuxrc (für ext3-System):
#!/static/sh insmod /modules/jbd.o insmod /modules/ext3.o mount -t proc proc /proc echo 256 > /proc/sys/kernel/real-root-dev umount /proc mount -t ext3 /dev/hda5 /mnt /bin/mount --bind /mnt/home/ffranz/newroot /mnt2 umount /mnt /static/pivot_root /mnt2 /mnt2/initrd
Im LILO dann einfach das angelegte Image als Initrd angeben und Kernel auf /home/ffranz/newroot/vmlinuz zeigen lassen :-).
Falls es andere Lösungen für dieses Problem gibt, dann würde ich mich freuen, darüber zu hören, aber im Netz habe ich bisher nix gefunden. Klar sollte auch sein, dass es hierbei nur um ein Beispiel gehen kann und eher auch um ein Proof-of-Concept, denn um eine absolut ausgearbeitete Lösung für jedermann. (dev/hda5, ffranz sind ja auf anderen Systemen anders.)
Ich denke auch, es zeigt, zumindest mir, mal wieder die fast unendlichen Möglichkeiten, die so ein Linux-System bietet.