4. Construire un système racine

Pour créer un système racine, il faut sélectionner les fichiers nécessaires au système pour fonctionner. Dans cette section nous décrivons comment créer un système racine compressé. Une option moins courante est de créer un système non compressé sur une disquette que l'on monte directement ; cette alternative est décrite dans la Section 9.1.

Un système racine doit contenir tout ce qui est nécessaire au bon fonctionnement d'un système Linux complet. Pour cela, le disque doit contenir un système Linux minimum :

Bien sûr, n'importe quel système devient utile dès que l'on peut faire tourner quelque chose dessus, et une disquette racine ne devient en général utilisable que lorsque vous pouvez faire quelque chose du genre :

Nous décrirons comment construire un système compressé, ainsi appelé car il est compressé sur disque et qu'une fois démarré, le noyau le décompresse dans un disque mémoire. Avec un système compressé vous pouvez faire tenir beaucoup de fichiers (à peu près six méga-octets) sur une disquette standard de 1440 ko. Puisque le système de fichiers est bien plus gros que la disquette, il ne peut être construit directement sur la disquette. Il nous faut le construire ailleurs et le compresser avant de le copier sur la disquette.

Pour créer un tel système racine, il vous faut un autre périphérique capable de stocker tous les fichiers avant leur compression. Ce périphérique doit pouvoir contenir à peu près quatre méga-octets. Plusieurs solutions s'offrent à vous :

Après avoir choisi une de ces options, préparez le PÉRIPHÉRIQUE avec :

dd if=/dev/zero of=PÉRIPHÉRIQUE bs=1k count=4096

Cette commande initialise à zéro le périphérique. Cette étape est importante pour la compression ultérieure du système de fichiers, afin que toutes les portions inutilisées soient remplies de zéros pour une compression maximum. Gardez cela à l'esprit si vous déplacez ou effacez des fichiers sur le système de fichiers. Le système de fichiers va désallouer correctement les blocs, mais ne va pas les initialiser à zéro à nouveau . Si vous effectuez beaucoup d'effacements et de copies, votre système de fichiers compressé risque d'être bien plus grand que nécessaire.

Ensuite, créez le système de fichiers. Le noyau Linux sait charger automatiquement deux types de système de fichiers dans un disque mémoire : minix et ext2, avec une préférence pour ext2. Si vous le choisissez, vous voudrez peut-être utiliser l'option -i afin de créer plus d'i-n½uds que par défaut ; -i 2000 est une bonne valeur qui vous évitera de tomber à court d'i-n½uds. Vous pouvez sinon économiser des i-n½uds en supprimant pas mal de fichiers /dev/ inutiles. mke2fs crée par défaut 360 i-n½uds sur une disquette de 1,44 Mo. Je trouve 120 i-n½uds largement suffisants pour ma disquette racine de secours, mais si vous conservez tous les périphériques dans le répertoire /dev vous dépasserez facilement les 360. L'utilisation d'un système racine compressé permet de créer un système de fichiers plus grand, contenant donc plus d'i-n½uds par défaut, mais vous pourrez quand même vouloir réduire le nombre de fichiers ou augmenter le nombre d'i-n½uds.

Vous allez donc taper une commande du genre :

mke2fs -m 0 -i 2000 PÉRIPHÉRIQUE

(Si vous utilisez un périphérique de boucle, le fichier que vous utilisez doit être indiqué à la place de ce PÉRIPHÉRIQUE. mke2fs vous demandera alors si vous voulez vraiment faire cela ; répondez oui.)

La commande mke2fs détectera automatiquement l'espace disponible et se configurera selon ce dernier. Le paramètre -m 0 permet de ne pas réserver d'espace pour root, et laisse donc plus d'espace disponible sur le disque.

Ensuite, montez le périphérique :

mount -t ext2 PÉRIPHÉRIQUE /mnt

(Vous devez créer un point de montage /mnt s'il n'existe pas encore.) Dans les sections suivantes, tous les répertoires destination sont supposés relatifs à /mnt.

Voici un minimum raisonnable de répertoires à créer sur votre système racine [1] :

  • /dev : Périphériques, nécessaires aux E/S ;

  • /proc : Répertoire de base nécessaire au système de fichiers proc ;

  • /etc : Fichiers de configuration du système ;

  • /sbin : Exécutables systèmes critiques ;

  • /bin : Exécutables de base considérés comme partie intégrante du système ;

  • /lib : Bibliothèques partagées nécessaires à l'exécution des programmes ;

  • /mnt : Un point de montage pour la maintenance des autres disques ;

  • /usr : Utilitaires et applications supplémentaires.

Trois de ces répertoires resteront vides sur les systèmes racine, il suffit donc de les créer avec mkdir. Le répertoire /proc n'est qu'une base sous laquelle le système proc est placé. /mnt et /usr ne sont que des points de montage utilisés une fois que le système amorce/racine tourne. Encore une fois, il suffit de créer ces répertoires.

Les quatre autres répertoires sont décrits dans les sections suivantes.

Tous les systèmes Linux ont besoin d'un répertoire /dev contenant un fichier spécial par périphérique accessible au système. Le répertoire en lui-même est normal, et peut être créé avec mkdir de la manière habituelle. Les fichiers spéciaux de périphérique doivent par contre être créés différemment, à l'aide de la commande mknod.

Il y a un raccourci par contre : copiez le contenu de votre répertoire /dev existant, puis supprimez ceux dont vous n'avez pas besoin. Il suffit juste de copier les fichiers spéciaux avec l'option -R. Cela copie le répertoire sans tenter de copier le contenu des fichiers. Attention à bien utiliser un R en majuscule ! Si vous utilisez l'option en minuscule -r, vous allez vous retrouver en train de copier le contenu complet de votre disque dur — ou au moins tout ce que pourra en contenir une disquette ! Prenez donc vos précautions, et utilisez par exemple les commandes :

cp -dpR /dev/fd[01]* /mnt/dev
cp -dpR /dev/tty[0-6] /mnt/dev

en supposant que la disquette est montée sur /mnt. Les options dp demandent la copie des liens symboliques en tant que lien, plutôt que celle du fichier qui se trouve au bout de celui-ci, et la conservation des attributs originaux des fichiers, pour garder les bons propriétaires.

Si vous voulez le faire vous-mêmes, utilisez ls -l pour afficher les numéros majeurs et mineurs des périphériques qui vous intéressent, et créez-les sur la disquette en utilisant mknod.

Quelle que soit la manière retenue pour copier les périphériques, il faut vérifier que tous les périphériques dont vous aurez besoin sont bien présents sur la disquette de secours. Par exemple, ftape utilise les périphériques de bande, qu'il vous faudra donc tous copier si vous comptez utiliser votre lecteur de bande depuis le disque amorce.

À noter qu'un i-n½ud est nécessaire pour chaque fichier de périphérique, et que les i-n½uds sont parfois une ressource rare, spécialement sur les systèmes de fichiers sur disquette. Il n'est donc pas idiot d'enlever du répertoire /dev de la disquette tous les fichiers de périphérique dont vous n'avez pas besoin. Bien des périphériques ne sont clairement pas nécessaires sur des systèmes spécifiques. Par exemple, si vous n'avez pas de disques SCSI vous pouvez tranquillement enlever tous les fichiers commençant par sd. De même, si vous ne comptez pas utiliser de port série vous pouvez supprimer tous les fichiers commençant par ttyS.

Si, en construisant le système de fichiers, vous obtenez l'erreur :

No space left on device

et que la commande df indique qu'il reste de l'espace disponible, c'est sans doutes qu'il n'y a plus d'i-n½ud disponible. Un df -i affichera l'utilisation des i-n½uds.

N'oubliez pas d'inclure les fichiers suivants dans le répertoire : console, kmem, mem, null, ram0, tty1.

Ce répertoire doit contenir un certain nombre de fichiers de configuration. Ce qu'il devrait contenir dépend des programmes que vous avez l'intention d'exécuter. Sur la plupart des systèmes, on peut les répartir en trois groupes :

  1. Nécessaires à tout moment, par exemple rc, fstab, passwd ;

  2. Peut-être nécessaires, mais on n'en est pas sûr ;

  3. Du bazar oublié là.

Les fichiers non essentiels peuvent être identifiés avec la commande :

ls -ltru

Les fichiers sont classés dans l'ordre inverse de dernière date d'accès, donc tout fichier qui n'est jamais lu peut être exclu d'une disquette racine.

Sur mes disquettes racine, je n'ai que 15 fichiers de configuration. Mon travail se réduit alors à gérer trois groupes de fichiers :

  1. Ceux que je dois configurer pour un système d'amorce et racine :

    1. rc.d/* : scripts de démarrage du système et de changement de niveau d'exécution ;

    2. fstab : liste des systèmes de fichiers à monter ;

    3. inittab : paramètres pour le processus init, le premier à être lancé au démarrage.

    4. gettydefs : paramètres pour le processus init, le premier à être lancé au démarrage.

  2. Ceux que je dois nettoyer pour un système d'amorce et racine :

    1. passwd : liste des utilisateurs, des répertoires utilisateurs, et cætera ;

    2. group : groupes d'utilisateurs ;

    3. shadow : mots de passe cachés des utilisateurs. Il se peut que vous n'ayez pas ce fichier ;

    4. termcap : la base de données de fonctionnalités des terminaux.

    Si la sécurité est importante, passwd et shadow doivent être nettoyés pour ne pas copier de mots de passe d'utilisateurs hors du système et pour qu'en cas de démarrage sur disquette, les logins indésirables soient rejetés.

    Assurez-vous que passwd contienne au moins root. Si vous comptez donner accès à d'autres utilisateurs, vérifiez l'existence de leurs répertoires utilisateurs et de leurs shells.

    termcap, la base de données de terminaux, fait en général plusieurs centaines de kilo-octets. Vous devrez faire du ménage dans la version de votre disquette d'amorce/racine pour ne conserver que le ou les terminaux que vous utilisez, ce qui se réduit en général à l'entrée linux ou linux-console.

  3. Le reste. Ils fonctionnent très bien tels quel, je ne les modifie donc pas.

Parmi tout cela, je n'ai en réalité que deux fichiers à configurer, et ils ne doivent contenir qu'étonnamment peu de choses.

Votre inittab doit être modifié pour que la ligne sysinit lance rc ou quelque autre script basique d'amorce. De plus, si vous ne souhaitez pas que les utilisateurs se loguent sur les ports série, commentez toutes les entrées getty qui font référence à des périphériques ttys ou ttyS à la fin de la ligne. Laissez les ports tty pour pouvoir vous connecter sur la console.

Un fichier inittab minimal contient ce qui suit :

id:2:initdefault
si::sysinit:/etc/rc
1:2345:respawn:/sbin/getty 9600 tty1
2:23:respawn:/sbin/getty 9600 tty2

Le fichier inittab décrit ce que va lancer le système dans divers états, dont le démarrage, le passage en mode multi utilisateurs, et cætera. Attention aux noms de fichiers référencés dans inittab ; si init ne peut trouver le programme, le disque d'amorce s'arrêtera, et vous n'aurez peut-être même pas de message d'erreur.

Notez que certains programmes ne peuvent être déplacés en raison d'autres programmes qui référencent en dur leur position. Par exemple sur mon système, /etc/shutdown référence en dur /etc/reboot. Si je déplace reboot vers /bin/reboot, et que je lance une commande shutdown, elle va échouer en ne trouvant pas le fichier reboot.

Pour le reste, copiez juste tous les fichiers texte de votre répertoire /etc, ainsi que tous les exécutables présents dans /etc dont vous n'êtes pas sûr de pouvoir vous passer. Basez-vous sur l'exemple de l'Annexe C. Exemple de contenu de répertoires sur un disque racine. Il vous suffira probablement de copier ces fichiers, mais les systèmes pouvant être très différents, il n'est pas certain que le même ensemble de fichiers sur votre système soit équivalent aux fichiers listés. La seule méthode sûre est de partir d'inittab et d'en déduire ce qui est nécessaire.

La plupart des systèmes utilisent maintenant un répertoire /etc/rc.d/ contenant des scripts shell pour les différents niveaux d'exécution. Il faut au minimum avoir un script rc unique, mais il peut être plus simple de carrément copier inittab et le répertoire /etc/rc.d depuis votre système puis de nettoyer les scripts shell dans le répertoire rc.d pour enlever tous les traitements inutiles pour un système sur disquette.

Le répertoire /bin est un endroit pratique pour tous les utilitaires nécessaires aux opérations de base, tels que ls, mv, cat et dd. Voir l'Annexe C. Exemple de contenu de répertoires sur un disque racine pour un exemple d'ensemble de fichiers pouvant aller dans les répertoires /bin et /sbin. Il ne contient aucun des utilitaires nécessaires à la récupération d'une sauvegarde, tels que cpio, tar et gzip. C'est parce que je place ceux-ci sur une disquette utilitaire séparée, pour conserver de la place sur la disquette d'amorce et racine. Une fois la disquette d'amorce/racine démarrée, elle est copiée sur le disque mémoire, laissant ainsi le lecteur de disquette libre pour en monter une autre, la disquette utilitaire. En général je la monte sur /usr.

La création d'une disquette utilitaire est décrite ci-dessous dans la Section 9.2 . Il est probablement souhaitable d'y maintenir une copie des mêmes versions d'utilitaires de sauvegarde que ceux utilisés pour écrire les sauvegardes, histoire de ne pas perdre de temps en essayant d'installer des versions qui ne peuvent pas lire vos bandes de sauvegarde.

Vérifiez que vous y mettez les programmes suivants : init, getty ou un équivalent, login, mount, un shell capable de faire tourner votre script rc, un lien de sh vers le shell en question.

Vous mettez dans /lib les bibliothèques partagées et les chargeurs nécessaires. Si les bibliothèques nécessaires ne sont pas trouvées dans /lib, le système ne pourra pas démarrer. Avec de la chance, un message vous expliquera pourquoi.

Pratiquement tous les programmes ont au moins besoin de la bibliothèque libc, libc.so.N, N étant le numéro de version courant. Vérifiez votre répertoire /lib, libc.so.N est en général un lien symbolique vers un fichier avec un numéro de version complet :

% ls -l /lib/libc.so*
-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*

Dans le cas présent, il vous faut libc-2.1.1.so. Pour trouver les autres bibliothèques nécessaires, il faut lancer la commande ldd sur tous les exécutables que vous prévoyez de mettre sur la disquette. Par exemple :

% 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)

Tous les fichiers à droite sont nécessaires. Le fichier peut en réalité être un lien symbolique.

Notez que certaines bibliothèques sont assez grosses et ne tiendront pas facilement sur votre système racine. Par exemple, la libc.so citée précédemment fait environ 4 méga-octets. Vous devrez probablement nettoyer les bibliothèques avant de les copier sur votre système racine. Reportez-vous à la Section 8 pour plus d'informations.

Il faut également inclure dans /lib un chargeur pour les bibliothèques. Il s'agira soit de ld.so (pour les bibliothèques a.out), soit de ld-linux.so (pour les bibliothèques ELF). Les versions récentes de ldd vous indiquent de quel chargeur vous avez besoin, comme dans l'exemple ci-dessus, mais de plus anciennes versions ne le font pas forcément. Si vous ne savez pas duquel vous avez besoin, utilisez la commande file sur la bibliothèque. Par exemple :

% 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