Eigene LiveCD bauen ohne catalyst
Aus Gentoo Linux Wiki
| Installationsmethoden • LiveCDs • Kernel & Hardware • Laptops & Notebooks • Portage • System • Netzwerke & Services • X • Software • Anderes • alphabetischer HOWTO Index |
Inhaltsverzeichnis |
[Bearbeiten] Einführung
Dieses HowTo zeigt, wie man für die x86-Architektur eine eigene LiveCD von Hand erstellt. Für die amd64-Architektur sollte das Vorgehen ebenfalls funktionieren. (Wem die notwendigen Anpassungen für weitere Plattformen bekannt sind, ist eingeladen, sie zu ergänzen)
Diese Methode bietet gegenüber dem Catalyst-Skript folgende Vorteile:
- Das Live-CD-System bleibt intakt und wird nicht während der Erstellung der LiveCD gelöscht. Das bietet die Möglichkeit, wie bei einem gewöhnlichen System, den Portage Tree zu synchronisieren, Pakete zu aktualisieren, zu löschen oder hinzuzufügen, ohne von vorne beginnen zu müssen. Das erspart nicht nur Arbeit, sondern auch sehr viel Zeit.
- In diesem HowTo wird Grub anstelle von Isolinux zum Booten verwendet. Das eröffnet dieselben Möglichkeiten, die man mit einem normalen System hat, wie zum Beispiel Kernelparameter zu ändern. Es bleibt natürlich freigestellt, trotzdem Isolinux zu verwenden.
[Bearbeiten] Voraussetzungen
Auf einen 700 MiB-Rohling passt ein etwa 2,1 GB großes System. Wir sollten etwa doppelt so viel freien Speicherplatz haben. Je nach dem, wieviele Pakete installiert werden sollen, können das also mehr als 4 GB sein.
Du solltest damit vertraut sein, wie man Gentoo von einem stage2 tarball aus installiert, denn genau das werden wir in diesem HowTo machen. Wenn Du unsicher bist, nimm das Handbuch zu Hilfe.
Es ist auch möglich, eine stage1-Installation durchzuführen, da das aber deutlich mehr Zeit benötigt und die meisten am Ende ohnehin ein "emerge -e world" ausführen, scheint die stage2-Installation die bessere Wahl zu sein.
Des Weiteren sollte der Kernel des laufenden Systems einkompiliert oder als Modul geladen haben:
- Loopback device support
- Second extended fs support (ext2)
Diese Pakete werden benötigt:
[Bearbeiten] Die Bau-Umgebung einrichten
Unsere Bau-Umgebung ist nur ein Verzeichnis in das wir 'chrooten' und in dem wir Gentoo installieren werden, wie wir es von der normalen Installation her kennen. Die Inhalte dieses Verzeichnisses kommen später auf die LiveCD. Im Folgenden heißt es source und ist ein Unterverzeichnis des ebenfalls neuen Verzeichnisses 'livecd' im eigenen Homeverzeichnis.
cd ~ mkdir -p livecd/source
Lade nun ein stage2 tarball in Dein Homeverzeichnis herunter. Wir verwenden hier ein i686 stage2 tarball(es ist allerdings auch möglich eine stage3 zu verwenden, jedoch muss man dann ein # emerge --update --newuse system ausführen), da es auf den meisten modernen PCs funktioniert. Sobald der Vorgang fertig ist, entpacke es in 'source'. Anschließend erstelle ein Verzeichnis newroot, welches während des Bootens verwendet werden wird.
(JDC: ein Verzeichnis new wird ebenfalls benötigt, sonst klappt's nachher mit dem Booten nicht!)
cd livecd/source tar xvjpf ~/stage2-i686-2005.0.tar.bz2 mkdir newroot mkdir new
Wer im laufenden System einen aktuellen und kompatiblen Portage Tree hat - das wird meistens der Fall sein - kann diesen mitsamt der distfiles verwenden, den folgenden Schritt überspringen und mit Gentoo installieren fortfahren.
[Bearbeiten] in Ausnahmefällen: Portage Snapshot herunterladen
Lade den aktuellen Portage Snapshot herunter in Dein Homeverzeichnis und entpacke ihn in Deinem neuen 'source'-Verzeichnis
cd livecd/source/usr/ tar xvjf ~/portage-<Datum>.tar.bz2
[Bearbeiten] Gentoo installieren
Als Nächstes richten wir die notwendigen mount-Punkte ein bevor wir ins 'source'-Verzeichnis 'chrooten' und die Installation starten. Als erstes proc:
cd livecd/source mount --bind /proc proc
Per Standard befindet sich der Portage Tree 'portage' in '/usr' und der Ordner 'distfiles' in '/usr/portage'. Wie oben bereits angekündigt, bietet es sich an, den Portage Tree und die distfiles des umgebenden Systems zu nutzen. Das spart viel Speicherplatz, Zeit und Bandbreite. Wer also die distfiles unterhalb von '/usr/portage' liegen hat, kann den Portage Tree und distfiles so einbinden:
mkdir usr/portage mount --bind /usr/portage usr/portage emerge --metadata
wer oben einen Portage-Snapshot entpackt hat und nun nur die distfiles einbinden will:
mkdir usr/portage/distfiles mount --bind /usr/portage/distfiles usr/portage/distfiles
Falls in diesem neuen System Pakete heruntergeladen werden müssen, passe die dafür notwendigen Konfigurationsdateien in '~/livecd/source/etc/' entsprechend an. Das kann insbesondere die 'resolv.conf' betreffen.
Nun 'chroote' nach 'source' und beginne mit der Installation. Vorher noch ein paar Hinweise zur '/etc/make.conf':
- Überlege Dir genau, welche USE-Variablen Du verwendest. Je mehr Du setzt, desto größer wird das System werden. Möglicherweise sogar so groß, dass es nicht mehr auf eine CD passt.
- Stelle sicher, dass 'livecd' gesetzt ist. Damit wird - zusammen mit dem beim Booten an den Kernel übergebenen 'cdroot'-Paramater - verhindert, dass die init-Skripte beim Booten unangebrachte Dinge machen, wie das Dateisystem des Wurzelverzeichnisses zu prüfen.
Hier die Installationsschritte im Groben:
cd livecd/source cp /etc/resolv.conf ./etc/ chroot . /bin/bash --login env-update source /etc/profile emerge -e system ln -sf /usr/share/zoneinfo/<Deine gewünschte Zeitzone> /etc/localtime emerge <notwendige Pakete wie udev, hotplug, logger, Kernel-Quellen...> rc-update add <benötigte Dienste wie z. B. coldplug, net.eth0, sysklogd> <default oder boot, wie es passt> emerge <weitere Pakete, die Du auf der CD möchtest, z. B. KDE, mplayer, usw.>
Bevor wir nun den Kernel konfigurieren (wir verwenden die gentoo-sources) und mit dem Bootloader installieren, ändern wir noch einige wichtige Konfigurationsdateien. Zunächst fstab:
/dev/loop0 / squashfs ro,defaults 0 0 none /proc proc defaults 0 0 none /dev/shm tmpfs nodev,nosuid,noexec 0 0
Das root-Verzeichnis werden wir später über ein loop device einbinden. Als nächstes richte die Konfigurationsdateien in '/etc' nach Deinen Vorstellungen ein. (rc.conf, conf.d/* usw.)
Falls Du den Kernel patchen willst, suche diese Patches zusammen.
Konfiguriere den Kernel und achte darauf, dass folgende Dinge fest einkompiliert werden (nicht als Module):
- squashfs filesystem
- iso9660 cdrom filesystem
- RAM Disk support und initrd support, maximale Größe 8MB
- Loopback block device support
- IDE/ATAPI cdrom device support
- Second extended fs support (ext2), verwenden wir für unser initrd Abbild
- tmpfs filesystem support
In den 'gentoo-sources' ist das alles enthalten. Falls Du einen anderen Kernel verwendest, der etwas davon nicht enthält (z. B. Squashfs), patche ihn noch entsprechend.
emerge gentoo-sources #anschließend patchen cd /usr/src/linux make menuconfig #konfiguriere den Kernel make bzImage modules modules_install cp arch/i386/boot/bzImage /boot/vmlinuz
Ich hatte das Problem, das die modules.* nicht gefunden wurden. Dies kann mit folgendem Befehl geloest werden:
modules-update --verbose --assume-kernel=2.6.17-gentoo-r8-livecd-r1
Zum Abschluss emergen und konfigurieren wir den Bootloader. Wir verwenden Grub, da er das Booten von CD-ROM unterstützt.
emerge grub
Hier die '/boot/grub/grub.conf' bzw. '/boot/grub/menu.lst'. Im Anschluss mehr dazu.
default 0
timeout 5
splashimage=(cd)/boot/grub/splash.xpm.gz
title=Gentoo Linux
root (cd)
kernel (cd)/boot/vmlinuz video=vesafb:1024x768-32 root=/dev/ram0 rw init=/linuxrc cdroot
initrd (cd)/boot/initrd
Von den Kernelparametern kannst Du 'video' weglassen, die anderen sind jedoch notwendig.
| Vorsicht: Vergiss nicht den symbolischen Link /boot/grub/menu.lst zu löschen und grub.conf in menu.lst umzubenennen. iso9660 unterstützt keine symlinks. Grub würde seine Konfiguration also nicht finden und nur seine Kommandozeile starten |
Damit der 'cdroot' Parameter von den Gentoo init-scripts richtig interpretiert wird musst Du noch die livecd-tools installieren:
USE="-opengl" emerge livecd-tools
[Bearbeiten] Das initrd Abbild erstellen
Während des Bootens läuft das meiste hier ab. Es ist eigentlich recht einfach, wenn Du erstmal den Dreh raus hast. Als erstes erstelle das Abbild. Wir verwenden hier ein initrd mit 8MB. Falls Du mehr brauchst oder mit deutlich weniger auskommst, lass Dich nicht daran hindern, die Größe anzupassen. Achte nur darauf, dass die Einstellungen für die maximale ramdisk-Größe in der Kernelkonfiguration stimmen.
touch /boot/initrd dd if=/dev/zero of=/boot/initrd bs=1024k count=8 losetup /dev/loop0 /boot/initrd mke2fs /dev/loop0 mkdir /mnt/initrd mount /dev/loop0 /mnt/initrd
Nun fülle das Abbild mit notwendigen Dateien und Verzeichnissen:
cd /mnt/initrd mkdir etc dev lib bin proc new cdrom touch linuxrc chmod +x linuxrc touch etc/mtab touch etc/fstab
linuxrc ist das, was ausgeführt wird, wenn Linux startet. Mehr dazu weiter unten.
Als Nächstes kopiere benötigte Dateien nach 'bin' und 'lib'. Nach 'bin' kopiere folgende Dateien:
/bin/sh /bin/cat /bin/mount /bin/umount /bin/mkdir /bin/chroot /bin/tar /bin/ls /sbin/pivot_root
Welche Dateien in lib benötigt werden, hängt von diesen Programmen ab. Um herauszufinden, welche das sind, starte ldd mit jeder dieser Dateien und kopiere die benötigten Dateien. Z. B.
ldd /bin/mount
linux-gate.so.1 => (0xffffe000)
libc.so.6 => /lib/libc.so.6 (0x4002e000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
cp /lib/libc.so.6 /mnt/initrd/lib/
cp /lib/ld-linux.so.2 /mnt/initrd/lib/
Genauso natürlich mit den restlichen Programmen.
Hier ein kleines 'quick & dirty' Skript, das diese Aufgabe abnehmen soll:
#!/bin/sh
#Hier stehen alle Befehle drin, die integriert werden sollen
CMDS=( sh ls cat mount umount mkdir chroot tar )
#Dies ist das Stammverzeichnis der Initrd, bei Bedarf anpassen
DIR=/mnt/initrd
for x in ${CMDS[@]}
do
cp -v /bin/${x} $DIR/bin
done
cp -v /sbin/pivot_root $DIR/bin
cd /lib
for x in ${CMDS[@]}
do
cp -v `ldd /bin/${x}|egrep lib|cut -d "=" -f1| cut -d " " -f1` $DIR/lib/
done
cp -v `ldd /sbin/pivot_root|egrep lib|cut -d "=" -f1| cut -d " " -f1` $DIR/lib/
#Notiz von rufus: Quick'n'Dirty stimmt - es läuft erst mit dem Zusatz-cut '|cut -d " " -f1'
Nun erstellen wir die nötigen Geräteknoten im '/dev'-Verzeichnis:
mknod /mnt/initrd/dev/console c 5 1 mknod /mnt/initrd/dev/null c 1 3 mknod /mnt/initrd/dev/hda b 3 0 mknod /mnt/initrd/dev/hdb b 3 64 mknod /mnt/initrd/dev/hdc b 22 0 mknod /mnt/initrd/dev/hdd b 22 64 mknod /mnt/initrd/dev/tty c 4 0 mknod /mnt/initrd/dev/loop0 b 7 0
Zum Schluss brauchen wir noch das linuxrc Skript. Es wird folgende Dinge übernehmen:
- Die erhaltenen Kernelparameter speichern und später /sbin/init übergeben
- Das CD-ROM-Laufwerk lokalisieren. (Wir suchen nur in hda, hdb, hdc und hdd. Falls Du damit rechnest, dass ein anderer Fall eintritt, erweitere es entsprechend)
- Die CD unter /cdrom mounten
- Das Squashfs-Abbild (in dem das komplette System zu einer einzelnen Datei komprimiert ist) unter /new mounten. Das wird das Dateisystem unseres Wurzelverzeichnisses, von dem nur gelesen werden kann
- Notwendige Mountpunkte, in denen auch geschrieben werden können muss, als tmpfs erstellen und mit den entsprechenden Dateien füllen.
- Schließlich noch das Wurzelverzeichnis in 'newroot' einhängen und den eigentlichen init Vorgang starten.
#!/bin/sh
export PATH=/bin
# Speichern der Kernel CMDLINE
mount -t proc none /proc
CMDLINE=`cat /proc/cmdline`
umount /proc
# CD Laufwerk mounten
CDROM=""
for x in hda hdb hdc hdd cdroms/cdrom0 cdroms/cdrom1 cdroms/cdrom2 cdroms/cdrom3
do
mount -t iso9660 -r /dev/${x} /cdrom > /dev/null 2>&1
if [ "$?" = "0" ]
then
CDROM="${x}"
break
fi
done
# CD-Laufwerk nicht gefunden
if [ "${CDROM}" == "" ]
then
exec /bin/sh
exit
fi
# Wurzelverzeichnis mounten und Verzeichnisse mit Lese- und Schreibzugriff erstellen
mount -t squashfs -o loop /cdrom/files/source.img /new > /dev/null 2>&1
mount -t tmpfs -o size=8m none /new/var > /dev/null 2>&1
mount -t tmpfs -o size=4m none /new/etc > /dev/null 2>&1
mount -t tmpfs -o size=32m none /new/tmp > /dev/null 2>&1
mount -t tmpfs -o size=32m none /new/root > /dev/null 2>&1
cd /new/var && tar xpf /cdrom/files/var.tar > /dev/null 2>&1
cd /new/etc && tar xpf /cdrom/files/etc.tar > /dev/null 2>&1
cd /new/root && tar xpf /cdrom/files/root.tar > /dev/null 2>&1
# Wurzelverzeichnis umsetzen und den eigentlichen init-Vorgang starten
cd /new
pivot_root . newroot
exec chroot . /bin/sh <<- EOF >dev/console 2>&1
exec /sbin/init ${CMDLINE}
EOF
Beachte, dass wir hier 2 x 32 MB, 1 x 8 MB und 1 x 4 MB tmpfs Dateisysteme verwenden. Dieser RAM steht Programmen nicht als Arbeitsspeicher zur Verfügung. Je nachdem, wo Du die CD einsetzen willst, solltest Du diese Werte anpassen.
Unser source-Verzeichnis ist nun bereit. Bevor wir fortfahren, sollten wir aber noch ein paar Änderungen vornehmen. '/var' enthält die Portage-Verzeichnisse 'cache' und 'db'. Die beiden sind groß und wir werden sie nach '/usr/lib/portage' verschieben um Platz in '/var' zu sparen.
cd /var mv cache db /usr/lib/portage/ ln -s /usr/lib/portage/cache cache ln -s /usr/lib/portage/db db
Wenn Du udev zum Gerätemanagement verwendest - was Du vermutlich tun wirst - und Dich darauf verlässt, dass Gentoo den Zustand der Geräte vor dem Neustart speichert, musst Du folgendes machen:
cd /lib mv udev-state /var/lib ln -s /var/lib/udev-state udev-state
Das liegt daran, dass '/lib' auf unserer CD-ROM nicht verändert werden kann.
Nun verlasse 'chroot' und unmounte 'proc' und 'portage' bzw. 'distfiles'.
[Bearbeiten] Die LiveCD erstellen
Die LiveCD zu erstellen erfordert folgende Schritte
- Nicht benötigte Verzeichnisse im source-Verzeichnis aufräumen (z. B. 'tmp' und 'var/tmp')
- Das Zielverzeichnis 'target' erzeugen, das wir verwenden werden, um das ISO-Abbild zu erstellen.
- Die Verzeichnisse mit Lese- und Schreibzugriff (wie 'etc' oder 'var') mit Hilfe von tar in 'target' speichern
- mit den Squashfs-Tools das 'source'-Verzeichnis in ein komprimiertes Abbild umwandeln
- und zuletzt noch das iso Abbild generieren
Um diese Schritte zu automatisieren, erstelle ein einfaches 'build'-Skript in 'livecd'
cd livecd touch build chmod +x build
Und hier ist das Skript, welches das ISO-Abbild als ~/livecd.iso erstellt:
#!/bin/bash
rm -rf target
mkdir target
cp -a source/boot target/
mkdir target/files
rm -rf source/var/tmp/*
rm -rf source/var/run/*
rm -rf source/var/lock/*
rm -rf source/tmp/*
rm -f source/etc/mtab
touch source/etc/mtab
cd source/etc/
tar cvpf ../../target/files/etc.tar * .[[:alnum:]]*
cd ../var/
tar cvpf ../../target/files/var.tar * .[[:alnum:]]*
cd ../root/
tar cvpf ../../target/files/root.tar * .[[:alnum:]]*
cd ../../
mksquashfs source/ target/files/source.img
mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot \
-boot-load-size 4 -boot-info-table -iso-level 4 \
-hide boot.catalog -o ~/livecd.iso target/
Überprüfe, ob die erzeugten tar-Dateien innerhalb der Größe der jeweiligen RAM-Laufwerke liegen, die Du erstellt hast (bei uns 4 MB für 'etc' und jeweils 32 MB für 'var' und 'root')
Ein großes 'source'-Verzeichnis zu "squashen" dauert ein ganzes Weilchen. Sobald das Skript fertig ist, kannst Du das Abbild brennen und von der CD booten. :)
[Bearbeiten] Tipps
Wenn Du häufig in das 'source'-Verzeichnis chrootest, um Änderungen vorzunehmen (z. B. Update oder Fehlerbehebung) kannst Du die Schritte auch mit einem einfachen Skript automatisieren. Wir nennen es hier 'work':
cd livecd touch work chmod +x work
das eigentliche Skript:
#!/bin/bash mount --bind /proc source/proc mount --bind /sys source/sys mount --bind /dev source/dev mount --bind /dev/pts source/dev/pts mount --bind /usr/portage source/usr/portage chroot source/ /bin/bash --login umount source/proc umount source/sys umount source/dev/pts umount source/dev umount source/usr/portage
(Falls Du nur die distfiles einbindest, passe es entsprechend an)
Vergiss nicht beim Betreten des Systems das hier noch auszuführen:
env-update source /etc/profile
und
emerge --metadata
falls Du den Portage Tree mit einbindest und im umgebenden System ein emerge --sync durchgeführt hast. So aktualisierst Du beide Portage Trees, aber lädst das Update nur einmal herunter.
Da ein einfaches bash-Skript nicht in der Lage ist, der neuen Umgebung Befehle zu übergeben, es aber unmountet, starte env-update und source/etc/profile auch nach Verlassen der Umgebung
Es ist wichtig, /dev zu mounten um Sachen wie X in der chroot-Umgebung starten zu können.
Eine weitere Sache ist die Größe des 'source'-Verzeichnisses. Wie Du sehen kannst, gibt es viele Dinge, die eine Menge Speicher brauchen, aber streng genommen auf einer LiveCD nicht gebraucht werden. Das betrifft insbesondere 'usr/src' und - falls Du nicht den Portage Tree des laufenden Systems verwendet hast - auch 'usr/portage'. Wenn Du diese nicht auf der CD haben willst, brauchst Du sie nicht zu löschen. mksquashfs bietet eine Option an, mit der man beliebige Verzeichnisse vom Abbild ausnehmen kann. So bleibt das 'source'-Verzeichnis intakt.
Sollte das Booten von CD während der Ausführung des linuxrc-Skripts schiefgehen, kannst Du jederzeit in der grub.conf den Kernelparameter 'init=/linuxrc' umändern in 'init=/bin/sh'. Dadurch bekommst Du beim Booten eine kleine shell im initrd Abbild. Von dort aus kannst Du dann die Befehle des linuxrc-Skripts nacheinander von Hand eintippen und versuchen so herauszufinden, wo das Problem liegt.
Ergänzungen oder Korrekturen in diesem HowTo sind gern gesehen. Falls Du also solche hast, zögere nicht, sie einzubauen.
Es ist nicht nötig das System zu 'bootstrapen'. Die CD kann sowohl von Systemen, von denen ein solcher erfolgt als auch jenen, bei denen das nicht der Fall ist, booten.
[Bearbeiten] Autologin
Wenn Du wie oben beschrieben die livecd-tools installiert hast, so sorgt der 'console=tty0' Kernelparameter auch gleich dafür dass Du automatisch nach dem Starten des Systems eingeloggt wirst. Andernfalls kannst Du mit folgenden Kommandos selbst dafür sorgen:
Chroote in das System der CD und emerge als erstes mingetty Dann modifiziere /etc/inittab (vorher eine Sicherung machen)
ersetze das
c1:12345:respawn:/sbin/agetty 38400 tty1 linux
mit diesem
c1:12345:respawn:/sbin/mingetty --autologin root --noclear tty1
für jedes tty, in dem Du automatisch als root eingeloggt werden möchtest.
Solltest Du die Meldung "Session opened for ....." erhalten, wenn Du die CD startest, emerge einen syslogger und füge es zum Boot-Runlevel hinzu,
[Bearbeiten] Alternatives build-Skript
Mit folgendem alternativen build-Skript wird die komplette Gentoo-Installation in ein neues Verzeichnis kopiert (livecd/target/files). Die Dokumentation (nicht die man pages) und das emerge-System (inklusive Portage Tree, falls vorhanden) werden daraus aber entfernt. Das Ergebnis kann damit um etwa 50MB kleiner werden. Allerdings benötigt das auch etwa 20 Minuten mehr Zeit.
#!/bin/bash rm -rf target mkdir target cp -a source/boot target/ mkdir target/files mkdir target/files/source cp -p -R -P -d source/ target/files rm -rf target/files/source/var/tmp/* rm -rf target/files/source/var/run/* rm -rf target/files/source/var/lock/* rm -rf target/files/source/var/cache/* rm -rf target/files/source/var/db/* rm -rf target/files/source/tmp/* rm -f target/files/source/etc/mtab touch target/files/source/etc/mtab rm -rf target/files/source/usr/portage rm -rf target/files/source/usr/lib/portage rm -rf target/files/source/usr/share/doc rm -rf target/files/source/root/.mc rm target/files/source/root/.bash_history rm target/files/source/var/log/emerge.log cd target/files/source/etc/ tar cvpf ../../../../target/files/etc.tar * .[[:alnum:]]* cd ../var/ tar cvpf ../../../../target/files/var.tar * .[[:alnum:]]* cd ../root/ tar cvpf ../../../../target/files/root.tar * .[[:alnum:]]* cd ../../ mksquashfs source/ source.img rm -rf source/ cd ../../ mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -iso-level 4 -hide boot.catalog -o ~/livecd.iso target/
(Sollte die lange Zeile am Schluss einen Umbruch enthalten, füge sie zu einer zusammen)
[Bearbeiten] Danksagung
Dieser Artikel basiert auf seiner englischen Version, die wiederum aus einem Thread im offiziellen Gentoo-Forum entstanden ist. Großen Dank daher an veezi, der sich die Arbeit gemacht hat, dieses Tutorial zu entwerfen.
