Het aanmaken van het rootbestandssysteem bestaat uit het selecteren van de bestanden die nodig zijn om het systeem te draaien. In deze sectie wordt beschreven hoe een gecomprimeerd rootbestandssysteem te bouwen. Een minder gebruikelijke optie bestaat uit het bouwen van een ongecomprimeerd bestandssysteem op een diskette dat direct als root wordt gemount; dit alternatief wordt beschreven in de paragraaf Niet-ramdisk rootbestandssystemen.
Op een rootbestandssysteem moet al datgene voorkomen wat nodig is om een volledig Linux-systeem te ondersteunen. Hiervoor moeten op de disk de minimum-vereisten voor een Linux-systeem worden opgenomen:
De basis bestandssysteemstructuuur,
Minimum set directory's: /dev, /proc, /bin, /etc, /lib, /usr, /tmp,
Basisset utility's: sh, ls, cp, mv, enz.,
Minimumset config bestanden: rc, inittab, fstab, enz.,
Devices: /dev/hd*, /dev/tty*, /dev/fd0, enz.,
Runtime library om in basisfuncties die door de utility's worden gebruikt te voorzien.
Uiteraard is ieder systeem pas dan van nut als je er iets onder kunt draaien, en een rootdiskette komt meestal alleen van pas als je iets kunt doen als:
Het controleren van een bestandssysteem op een andere disk, om bijvoorbeeld je rootbestandssysteem op een harddisk te controleren, moet je Linux van een andere disk kunnen booten, zoals je dat kan met een rootdiskettesysteem. Vervolgens kun je fsck dan uitvoeren op je oorspronkelijke rootdisk terwijl het niet is gemount.
Het herstellen van je gehele of gedeeltelijke oorspronkelijke rootdisk vanaf een backup door gebruik te maken van archief- en compressie- utility's zoals cpio, tar, gzip en ftape.
We zullen beschrijven hoe een gecomprimeerd bestandssysteem op een ramdisk te bouwen. Het wordt zo genoemd omdat het op disk is gecomprimeerd en bij het booten op een ramdisk wordt gedecomprimeerd. Met een gecomprimeerd bestandssysteem kunnen er veel bestanden (bij benadering zes megabyte) op een standaard 1440K diskette. Omdat het bestandssysteem veel groter is dan een diskette, kan het niet op de diskette worden gebouwd. We moeten het elders bouwen, het comprimeren, en dan naar diskette kopiëren.
Om een dergelijk rootbestandssysteem te bouwen, heb je een reserve device nodig welke groot genoeg is alle bestanden voor compressie te bevatten. Je hebt een device nodig dat capabel is om ongeveer vier megabyte te bevatten. Je hebt verscheidene keuzes:
Gebruik een ramdisk (DEVICE = /dev/ram0). In dit geval wordt geheugen gebruikt om een diskette te simuleren. De ramdisk moet groot genoeg zijn voor een bestandssysteem van passende grootte. Controleer je configuratiebestand (/etc/lilo.conf) op een regel als RAMDISK = nnn waarmee het maximum RAM dat in beslag kan worden genomen door een ramdisk als je gebruik maakt van LILO. De standaardwaarde is wat voldoende zou moeten zijn. Het is beter niet te proberen een dergelijke ramdisk te gebruiken op een computer met minder dan 8MB RAM. Controleer voor de zekerheid of je een device hebt als /dev/ram0, /dev/ram of /dev/ramdisk. Als dit niet zo is, maak /dev/ram0 dan aan met mknod (major nummer 1, minor 0).
Als je een ongebruikte harddiskpartitie hebt die groot genoeg is (verscheidene megabytes) dan is dit acceptabel.
Gebruik een loopback device, waarmee het mogelijk is een diskbestand als een device te laten fungeren. Door gebruik te maken van een loopback-device kun je op je harddisk een bestand van drie megabyte aanmaken en er het bestandssysteem op bouwen.
Typ man losetup voor instructies over het gebruik van loopback devices. Als je losetup niet hebt, kun je het samen met compatibele versies van mount en unmount verkrijgen vanuit het package util-linux in de directory ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/.
Als je op je systeem geen loop-device (/dev/loop0 /dev/loop1, enz.) hebt, zal je het aan moeten maken met ``mknod /dev/loop0 b 7 0''. Zodra je deze speciale mount en umount binary's hebt geïnstalleerd, maak je op een hardisk met voldoende capaciteit een tijdelijk bestand aan (bv, /tmp/fsfile). Je kunt een opdracht gebruiken als:
dd if=/dev/zero of=/tmp/fsfile bs=1k count=nnn |
Gebruik hieronder dit bestand in plaats van DEVICE. Wanneer je een mount-opdracht aanroept, moet je de optie -o loop aan mount meegeven om aan te geven dat mount een loopback-device gebruikt. Bijvoorbeeld:
mount -o loop -t ext2 /tmp/fsfile /mnt |
Nadat je voor één van deze opties hebt gekozen, prepareer je het DEVICE met:
dd if=/dev/zero of=DEVICE bs=1k count=4096 |
Deze opdracht vult het device op met nullen.
![]() | Het device met nullen opvullen is van groot belang omdat het bestandssysteem later zal worden gecomprimeerd, dus alle ongebruikte delen zouden met nullen moeten worden opgevuld om een maximum compressie te bereiken. Houd dit feit in gedachten wanneer je bestanden vanaf je rootbestandssysteem verwijdert. Het bestandssysteem zal de blokken correct vrijgeven, maar het vult ze niet weer met nullen op. Als je veel verwijdert en kopieert, kan je gecomprimeerde bestandssysteem uiteindelijk veel groter worden dan nodig is. |
Maak vervolgens het bestandssysteem aan. De Linux-kernel herkent voor rootdisks twee typen bestandssystemen die automatisch naar ramdisk worden gekopieerd. Dit zijn minix en ext2, waarvan ext2 de voorkeur heeft. Als je ext2 gebruikt, vind je het wellicht handig de optie -i mee te geven om meer inodes dan de standaardwaarde op te geven; -i 2000 wordt aanbevolen zodat je geen inodes te kort komt. Als alternatief kun je op inodes besparen door veel van de onnodige /dev bestanden te verwijderen. mke2fs zal op een 1.44Mb diskette standaard 360 inodes aanmaken. Ik merkte dat 120 inodes op mijn huidige rescue rootdiskette ruim voldoende is, maar als je alle devices in de directory /dev opneemt, dan zal het de 360 makkelijk overschrijden. Het gebruik van een gecomprimeerd rootbestandssysteem maakt een groter bestandssysteem mogelijk, en vandaar standaard meer inodes, maar mogelijk moet je toch het aantal bestanden nog verminderen of het aantal inodes verhogen.
Dus de opdracht die je gaat gebruiken, ziet er ongeveer zo uit:
mke2fs -m 0 -i 2000 DEVICE |
(Als je van een loopback-device gebruik maakt, moet DEVICE worden vervangen door het diskbestand).
De opdracht mke2fs zal automatisch de beschikbare ruimte detecteren en zichzelf dienovereenkomstig configureren. De parameter ``-m 0'' voorkomt dat er ruimte voor root wordt gereserveerd, en daardoor blijft er meer bruikbare ruimte op de disk over.
Mount dan het device:
mount -t ext2 DEVICE /mnt |
Hier is een redelijke minimumset directory's voor je rootbestandssysteem [1]:
/dev -- Devices, vereist voor I/O
/proc -- Directory stub vereist voor het proc-bestandssysteem
/etc -- Systeemconfiguratiebestanden
/sbin -- Kritieke systeembinary's
/bin -- Essentiële binary's die worden aangemerkt als onderdeel van het systeem
/lib -- Shared library's om te voorzien in run-time support
/mnt -- Een mountpoint voor het beheer van andere disks
/usr -- Extra utility's en applicaties
Drie van deze directory's zullen op het rootbestandssysteem leeg zijn, dus ze hoeven alleen met mkdir te worden aangemaakt. De directory /proc is eigenlijk een stub waaronder het proc-bestandssysteem wordt geplaatst. De directory's /mnt en /usr zijn slechts mountpoints voor gebruik nadat het boot/root systeem draait. Vandaar nogmaals, hoeven deze directory's alleen te worden aangemaakt.
De overblijvende vier directory's worden in de volgende secties beschreven.
Een /dev directory met voor alle devices een speciaal bestand om door het systeem te worden gebruikt is voor ieder Linux-systeem verplicht. De directory zelf is een normale directory en deze kan met mkdir op de gebruikelijke wijze worden aangemaakt. De speciale bestanden voor de devices moeten echter op een speciale manier, met de opdracht mknod worden aangemaakt.
Er is echter een kortere weg. Kopieer de inhoud van je bestaande /dev directory, en verwijder die bestanden die je niet wilt. Het enige waar je op moet letten is dat je de speciale bestanden voor de devices kopieert met de optie -R. Hiermee zal de directory worden gekopieerd zonder dat er zal worden geprobeerd de inhoud van de bestanden te kopiëren. Zorg ervoor dat je de hoofdletter R gebruikt. De opdracht is:
cp -dpR /dev /mnt |
Als je het op een moeilijke manier wilt doen, gebruik je ls -l om de major en minor device-nummers voor de gewenste devices weer te geven, en maak je ze aan op de diskette met mknod.
Alhoewel de devices zijn gekopieerd, loont het de moeite na te kijken dat alle door jou benodigde devices op de rescue-diskette zijn geplaatst. ftape maakt bijvoorbeeld gebruik van tape devices, dus zal je alle tape devices moeten kopiëren als je van plan bent je floppy tapedrive vanaf de bootdisk te benaderen.
Voor ieder speciaal apparaatbestand is een inode vereist, en inodes kunnen zo nu en dan een schaarse bron vormen, vooral op diskette bestandssystemen. Het heeft daarom zin alle niet benodigde speciale bestanden voor de devices uit de directory /dev van de diskette te verwijderen. Als je bijvoorbeeld geen SCSI-disks hebt, kun je alle apparaatbestanden te beginnen met sd gerust verwijderen. Op vergelijkbare wijze kunnen alle apparaatbestanden beginnend met cua worden verwijderd, als je niet van plan bent je seriële poort te gaan gebruiken.
![]() | Zorg er in ieder geval voor dat je de volgende bestanden in deze directory opneemt: console, kmem, mem, null, ram0 en tty1. |
In deze directory staan belangrijke configuratiebestanden. Op de meeste systemen kunnen deze in drie groepen worden onderverdeeld:
Ten alle tijden vereist, b.v. rc, fstab, passwd.
Mogelijk nodig, maar niemand is daar al te zeker van.
Rommel die erin is geslopen.
ls -ltru |
Op mijn rootdiskettes heb ik het aantal configuratiebstanden onder de 15 weten te houden. Dit reduceert mijn werk tot 3 sets bestanden:
Degenen die ik voor een boot/root-systeem moet configureren:
rc.d/* -- systeem opstartscripts en scripts benodigd bij het wijzigen van het runlevel.
fstab -- lijst met te mounten bestandssystemen
inittab -- parameters voor het init-proces, het eerste proces dat bij de systeemstart wordt gestart.
Degenen die ik voor een boot/root-systeem op zou kunnen knappen:
passwd -- lijst met gebruikers, homedirectory's, enz.
group -- gebruikersgroepen.
shadow -- wachtwoorden van gebruikers. Wellicht dat je deze niet hebt.
termcap -- de terminal capaciteiten database.
Als beveiliging van belang is, dan zouden passwd en shadow moeten worden geoptimaliseerd om het kopiëren van gebruikerswachtwoorden van het systeem te voorkomen zodat ongewenste logins worden verworpen wanneer je vanaf een diskette boot.
Zorg ervoor dat in passwd om z'n minst root voorkomt. Als je van plan bent andere gebruikers in te laten loggen, zorg er dan voor dat de directory's en shells aanwezig zijn.
termcap, de terminal database is meestal verscheidene kilobytes groot. De versie die je op je boot-/rootdiskette gebruikt, zou zo moeten worden geoptimaliseerd, dat het slechts de te gebruiken termainal(s) bevat, wat gewoonlijk slechts het linux of linux-console veld is.
De rest. Ze zijn op het moment actief dus laat ik ze met rust.
Daarbuiten hoefde ik slechts twee bestanden te configureren en de inhoud daarvan is verbazingwekkend weinig.
In rc zou moeten staan:
#!/bin/sh /bin/mount -av /bin/hostname Kangaroo |
In fstab zou op z'n minst moeten staan:
/dev/ram0 / ext2 defaults /dev/fd0 / ext2 defaults /proc /proc proc defaults |
Je moet je inittab zodanig wijzigen dat de regel sysinit rc, of welk bootscript dan ook zal worden gebruikt, wordt uitgevoerd. Als je er tevens zeker van wilt zijn dat gebruikers niet in kunnen loggen via seriële poorten, plaats dan een commentaarteken voor alle velden met getty waarin een ttys of ttyS device aan het einde van de regel is opgenomen. Laat de tty poorten staan, zodat je op de console in kunt loggen.
Een minimaal inittab bestand ziet er als volgt uit:
id:2:initdefault: si::sysinit:/etc/rc 1:2345:respawn:/sbin/getty 9600 tty1 2:23:respawn:/sbin/getty 9600 tty2 |
Een aantal programma's kan niet naar elders worden verplaatst, omdat andere programma's hun lokaties hebben ingeprogrammeerd. Op mijn systeem bijvoorbeeld is in /etc/shutdown /etc/reboot ingeprogrammeerd. Als ik reboot naar /bin/reboot verplaats, en dan de opdracht shutdown aanroep, zal de uitvoering ervan mislukken omdat het 't bestand reboot niet kan vinden.
Kopieer voor de rest alle tekstbestanden plus alle uitvoerbare bestanden in de directory /etc waarvan je niet zeker bent of je ze niet nodig hebt. Raadpleeg als een leidraad de voorbeeldlisting in Aanhangsel C. Waarschijnlijk is het voldoende alleen die bestanden te kopiëren, maar systemen verschillen nogal, dus je kunt er niet zeker van zijn dat dezelfde set bestanden op je systeem equivalent is aan de bestanden in de lijst. De enige zekere methode is te beginnen bij inittab en alles uit te werken wat nodig is.
Op de meeste systemen wordt nu gebruik gemaakt van een /etc/rc.d/ directory waarin alle shell-scripts voor de verschillende runlevels staan. Het minimum is een enkel rc script, maar het kan eenvoudiger door gewoon het bestand inittab en de directory /etc/rc.d vanaf je bestaande systeem te kopiëren en de shell-scripts in de directory rc.d te ontdoen van verwerkingen die niet relevant zijn voor een systeemomgeving voor op diskette.
De directory /bin is een prima plaats voor extra utility's die je nodig hebt voor de uitvoering van basisbewerkingen, utility's zoals ls, mv, cat en dd. Zie Aanhangsel C voor een voorbeeldlijst met bestanden die in de directory's bin en /sbin worden geplaatst. Hierin zijn geen utility's opgenomen die nodig zijn om gegevens vanaf een backup terug te zetten, zoals cpio, tar en gzip. Dat komt doordat ik die op een aparte utility-diskette plaats, om ruimte te besparen op de boot-/rootdiskette. Zodra de boot-/rootdiskette is geboot, wordt het naar de ramdisk gekopieerd waarbij het diskettestaion vrijkomt om een andere diskette, de utility-diskette te kunnen mounten. Ik mount deze gewoonlijk als /usr.
De aanmaak van een utility-diskette wordt hierna beschreven in de paragraaf Bouwen van een utility-disk. Waarschijnlijk is het wenselijk een kopie van dezelfde versie backuputitily's, die worden gebruikt om de backups te schrijven, te beheren, zodat je geen tijd verspilt bij het proberen te installeren van versies die je backuptapes niet in kunnen lezen.
![]() | Verzeker je ervan dat je de volgende programma's opneemt: init, getty of equivalent, login, mount, een shell die capabel is voor het uitvoeren van je rc-scripts, een link vanuit sh naar je shell. |
In /lib plaats je de benodigde shared library's en loaders. Als de benodigde library's niet in de directory /lib worden gevonden dan zal het systeem niet kunnen booten. Als je geluk hebt, zie je wellicht een foutmelding over wat er aan de hand is.
Bijna ieder programma heeft op z'n minst de library libc, libc.so.N nodig; de N staat voor het huidige versienummer. Controleer je /lib directory. Het bestand libc.so.N is gewoonlijk een symlink naar een bestandsnaam met een volledig versienummer:
% ls -l /lib/libc* -rwxr-xr-x 1 root root 4016683 Apr 16 18:48 libc-2.1.1.so* lrwxrwxrwx 1 root root 13 Apr 10 12:25 libc.so.6 -> libc-2.1.1.so* |
In dit geval gebruik je libc-2.1.1.so. Om achter de andere library's te komen, neem je alle binaire bestanden door die je van plan bent op de diskette te plaatsen en controleer je daarvan de afhankelijkheden met ldd. Bijvoorbeeld:
% ldd /sbin/mke2fs libext2fs.so.2 => /lib/libext2fs.so.2 (0x40014000) libcom_err.so.2 => /lib/libcom_err.so.2 (0x40026000) libuuid.so.1 => /lib/libuuid.so.1 (0x40028000) libc.so.6 => /lib/libc.so.6 (0x4002c000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) |
Een aantal library's is nogal groot en ze zullen niet zo gemakkelijk op je rootbestandssysteem passen. De hiervoor genoemde libc.so bijvoorbeeld is ongeveer 4 meg. Waarschijnlijk zal je library's moeten strippen wanneer je ze naar je rootbestandssysteem kopieert. Zie paragraaf Terugbrengen van de grootte van het rootbestandssysteem voor instructies.
In /lib moet je tevens een loader voor de library's opnemen. De loader zal óf ld.so (voor A.OUT library's, die niet langer algemeen zijn) óf ld-linux.so (voor ELF library's) zijn. Nieuwere versies van ldd vertellen je exact welke loader nodig is, zoals in het voorbeeld hiervoor, maar oudere versies mogelijk niet. Als je niet zeker weet welke je nodig hebt, pas dan de opdracht file toe op de library. Bijvoorbeeld:
% file /lib/libc.so.4.7.2 /lib/libc.so.5.4.33 /lib/libc-2.1.1.so /lib/libc.so.4.7.2: Linux/i386 demand-paged executable (QMAGIC), stripped /lib/libc.so.5.4.33: ELF 32-bit LSB shared object, Intel 80386, version 1, stripped /lib/libc-2.1.1.so: ELF 32-bit LSB shared object, Intel 80386, version 1, not stripped |
Kopieer de specifieke loader(s) die je nodig hebt naar het rootbestandssysteem dat je aan het bouwen bent. Library's en loaders zouden zorgvuldig moeten worden gecontroleerd met de opgenomen library's. Als de kernel een benodigde library niet kan laden, kan het zijn dat de kernel zonder foutmelding blijft hangen.
Mogelijk zijn er voor je systeem dynamisch laadbare library's nodig die niet zichtbaar zijn voor ldd. Als je hierin niet voorziet, kan het zijn dat je problemen krijgt bij het inloggen of het gebruiken van je bootdisk.
Als er op je systeem gebruik wordt gemaakt van PAM (Pluggable Authentication Modules), moet je er voorzieningen voor treffen op je bootdisk. Kort gezegd is PAM een geraffineerde modulaire methode voor de authenticatie van gebruikers en het beheren van de toegang tot de services voor gebruikers. Een eenvoudige manier om vast te stellen of je systeem gebruik maakt van PAM is ldd op het uitvoerbare bestand login toe te passen; als in de uitvoer libpam.so voorkomt, heb je PAM nodig.
Gelukkig heb je bij bootdisks gewoonlijk niets met beveiliging van doen aangezien iedereen die fysiek toegang heeft tot een computer, gewoonlijk alles kan doen wat hij/zij wil. Daarom kun je PAM effectief deactiveren door het aanmaken van een eenvoudig /etc/pam.conf bestand in je rootbestandssysteem dat er ongeveer zo uitziet:
OTHER auth optional /lib/security/pam_permit.so OTHER account optional /lib/security/pam_permit.so OTHER password optional /lib/security/pam_permit.so OTHER session optional /lib/security/pam_permit.so |
Deze configuratie staat iedereen toegang tot de bestanden en services op je computer toe. Als beveiliging op je bootdisk je om één of andere reden lief is, zal je de gehele of gedeeltelijke PAM setup van je harddisk naar je rootbestandssysteem moeten kopiëren. Lees de PAM documentatie zorgvuldig door, en kopieer alle benodigde library's in /lib/security naar je rootbestandssysteem.
Je moet tevens /lib/libpam.so op je bootdisk plaatsen. Maar dit wist je al aangezien je ldd op /bin/login toepaste, waarmee deze afhankelijkheid werd getoond.
Als je glibc (ala libc6) gebruikt, zal je voorzieningen moeten treffen voor name services anders zal je niet in kunnen loggen. Het bestand /etc/nsswitch.conf bestuurt database lookups voor diverse services. Als je van plan bent services vanaf het netwerk te benaderen (bv, DNS of NIS lookups) dan moet je een eenvoudig nsswitch.conf bestand prepareren dat er ongeveer zo uitziet:
passwd: files shadow: files group: files hosts: files services: files networks: files protocols: files rpc: files ethers: files netmasks: files bootparams: files automount: files aliases: files netgroup: files publickey: files |
Als je van plan bent het netwerk vanaf je bootdisk te benaderen, wil je misschien een nauwgezetter bestand nsswitch.conf aanmaken. Zie de nsswitch manpage voor details. Je moet een bestand /lib/libnss_ service.so.1 opgeven voor iedere service die je specificeert.
Als je een modulaire kernel hebt, overweeg dan welke modules je na het booten vanaf je bootdisk wilt laden. Wellicht dat je ftape en zftape modules op wilt nemen als je backuptapes op floppytape zijn, modules voor SCSI-devices als je ze hebt, en mogelijk modules voor PPP of SLIP ondersteuning als je het net in noodgeval wilt benaderen.
Deze modules kunnen in /lib/modules worden geplaatst. Je zou ook insmod, rmmod en lsmod op moeten nemen. En afhankelijk van of je modules automatisch wilt laden, ook modprobe, depmod en swapout. Als je kerneld gebruikt, neem het dan samen met /etc/conf.modules op.
Het belangrijkste voordeel bij het gebruik van modules is echter dat je niet kritieke modules naar een utility-disk kunt verplaatsen en ze kunt laden wanneer ze nodig zijn. Dus gebruik je minder ruimte op je rootdisk. Als je met veel verschillende devices te maken hebt, heeft deze benadering de voorkeur in vergelijking met het bouwen van één zeer grote kernel met veel ingebouwde drivers.
![]() | Om een gecomprimeerd ext2 bestandssysteem te kunnen booten, moet je ramdisk en ext2 ondersteuning hebben ingebouwd. Ze kunnen niet als modules worden toegevoegd. |
Een aantal systeemprogramma's, zoals login, produceert foutmeldingen als het bestand /var/run/utmp en de directory /var/log niet voorkomen. Dus:
mkdir -p /mnt/var/{log,run{ touch /mnt/var/run/utmp |
Nadat je tenslotte alle benodigde library's hebt ingesteld, pas je ldconfig toe op /etc/ld.so.cache op het rootbestandssysteem opnieuw aan te maken. De cache vertelt de loader waar het de library's vindt. Roep de volgende opdrachten aan voor het opnieuw maken van ld.so.cache:
chdir /mnt; chroot /mnt /sbin/ldconfig |
Zodra je klaar bent met het construeren van het rootbestandssysteem, unmount je het, kopieer je het naar een bestand en comprimeer je het:
umount /mnt
dd if=DEVICE bs=1k | gzip -v9 > rootfs.gz |
[1] | De directorystructuur die hier wordt gepresenteerd is alleen voor het gebruik van een rootdiskette. Echte Linux-systemen hebben een complexere en meer gedisciplineerde set gedragslijnen, genaamd de Filesystem Hierarchy Standard, voor het vaststellen waar welke bestanden in staan). |