Linux From Scratch (partie 3)

Mon script d’installation personnalisé

Source de l’image illustrant l’article

ATTENTION! Tout comme la procédure officielle, cette procédure personnalisée présente un risque pour le système hôte installé sur votre ordinateur. Il est vivement recommandé d’utiliser une machine de test.

Je me suis permis de prendre quelques libertés avec la procédure officielle d’installation du système Linux From Scratch. En fait, je souhaite rassembler la totalité des instructions dans un seul script (start.sh) et avec un système de balises déplaçables, donner la possibilité à l’utilisateur de n’exécuter que des parties bien précises du code. Je ne sais pas encore si mon projet est réaliste mais les premiers tests sont prometteurs. Voici comment j’ai procédé:

Avant de lancer le script, j’ai créé un nouvel utilisateur nommé lfs. Je l’ai immédiatement ajouté au groupe sudo et j’ai redémarré mon ordinateur pour prendre en compte les changements:

sudo groupadd lfs
sudo useradd -s /bin/bash -g lfs -m -k /dev/null lfs
sudo usermod -aG sudo lfs
reboot

Je me suis reconnecté en tant qu’utilisateur lfs. Puis, j’ai copié les scripts suivants dans le répertoire /home/lfs:

  • start.sh (fichier lanceur)
  • wget-list (liste des paquets à télécharger sous forme d’archives)
  • md5sums (sommes de contrôle)

J’ai rendu l’utilisateur lfs récursivement propriétaire de son répertoire avec la commande suivante:

sudo chown -R lfs:lfs /home/lfs

J’ai donné le droit d’exécution au script start.sh.

chmod +x /home/lfs/start.sh

J’ai lancé ce script en tant que superutilisateur lfs (sudo). Le code s’est exécuté de la balise n° 1 à la balise n° 2. Il s’est interrompu automatiquement à la commande source /home/lfs/.bash_profile.

J’ai relancé le script après avoir DECOMMENTÉ la balise ouvrante n° 1 et la balise fermante n° 2. Cela a eu pour effet de créer un commentaire multilignes qui a neutralisé l’exécution de cette partie du code. Le code s’est exécuté seulement à partir de la balise n° 2.

Ne JAMAIS neutraliser les instructions suivantes:

export MAKEFLAGS=-j`nproc --all`
cd /mnt/lfs/sources

Si vous utilisez la même procédure que moi, à partir de la balise n° 2 (décompression des archives et installation des paquets), vous pouvez très bien exécuter le script en renvoyant les erreurs de compilation dans un fichier errors.txt. Cela facilite grandement le débogage.

/home/lfs/start.sh 2> /home/lfs/errors.txt

Vous pouvez également déplacer les balises END_COMMENT comme bon vous semble et exécuter le script en plusieurs fois ou bien exécuter seulement une partie du script.

Compilation croisée des outils temporaires

Dans le chapitre précédent, nous avons construit une chaîne de compilation croisée. Nous avons en quelque sorte fabriqué un outil qui va nous servir à compiler et installer des paquets nécessaires à l’élaboration de notre système Linux From Scratch. Ces paquets seront réinstallés définitivement à l’intérieur de l’environnement chroot.

m4-1.4.19

Nous allons commencer par le paquet m4-1.4.19. Il s’agit d’un macroprocesseur qui remplace du texte dans les applications de programmation, en utilisant des macros définis par l’utilisateur. Voici un petit exemple :

define(WEBSITE,`Miamondo<https://miamondo.org>')    

WEBSITE
Miamondo<https://miamondo.org>

ncurses-6.2

ncurses-6.2 est une bibliothèque qui offre à l’utilisateur plusieurs fonctionnalités telles qu’une interface couleur, des menus déroulants, la possibilité d’utiliser sa souris dans un mode semi-graphique, etc… Voici un exemple d’interface utilisateur générée par ncurses :

Bash-5.1.8

Le Bourne-Again shell est un interpréteur de commandes qui selon la définition de Wikipédia, permet d’accéder aux fonctionnalités internes du système d’exploitation. Toujours selon Wikipédia, Bash exécute quatre opérations fondamentales:

  1. Il fournit une liste de commandes permettant d’opérer sur l’ordinateur (lancement de programmes, copie de fichiers, etc.) ;
  2. Il permet de regrouper ces commandes dans un fichier unique appelé script ;
  3. Il vérifie la ligne de commande lors de son exécution ou lors d’une éventuelle procédure de vérification et renvoie un message d’erreur en cas d’erreur de syntaxe ;
  4. En cas de validation, chaque ligne de commande est interprétée, c’est-à-dire traduite dans un langage compréhensible par le système d’exploitation, qui l’exécute alors.

Bash s’utilise notamment dans un émulateur de terminal tel que lxterminal ou xterm. Voici un exemple de la mise à jour d’une distribution Linux Mint avec la commande Bash apt update.

Coreutils-8.32

Coreutils-8.32 est un paquet très important puisqu’il fournit de nombreuses fonctionnalités basiques telles que rm, chmod, chown, mkdir, ls, etc… Ces commandes sont nécessaires à la bonne marche d’un système d’exploitation de type Unix. Cliquez sur le lien en début de paragraphe pour accéder au contenu de ce paquet.

DiFFUTILS-3.8

Le paquet Diffutils-3.8 contient les programmes montrant les différences entre fichiers ou répertoires. Voici les détails.

File-5.40

Le paquet file-5.40 contient un outil pour déterminer le type d’un fichier ou des fichiers donnés.

Voici le reste des outils temporaires qui vont eux aussi être compilés :

Findutils-4.8.0

Gawk-5.1.0

Grep-3.7

Gzip-1.10

Make-4.3

Patch-2.7.6

Sed-4.8

Tar-1.34

Xz-5.2.5

Binutils-2.37 — Passe 2

GCC-11.2.0 — Passe 2

Linux From Scratch (partie 2)

Dans la partie 1, nous avons installé les bases de notre futur système LFS. Nous avons:

  • créé une partition dédiée,
  • téléchargé les archives dans le répertoire /mnt/lfs/sources,
  • créé quelques répertoires nécessaires à la construction,
  • ajouté un nouvel utilisateur (lfs)
  • ouvert un shell de connexion pour l’utilisateur lfs.

Nous en sommes à ce stade. À présent, nous sommes connectés en tant qu’utilisateur lfs, et dans cette partie, nous allons commencer par configurer un environnement de travail sain. Nous allons remplacer le shell en cours par un nouveau shell bien plus propre. Nous n’aurons pas à craindre qu’une variable provenant du système hôte interfère avec notre système « cible » et l’endommage. C’est la commande exec env -i qui se charge de l’opération.

cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF

Dans cette optique de sécurité, nous créons également un nouveau fichier .bashrc. Il est important de séparer le système cible du système hôte le plus tôt possible.

cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF

Enfin, nous chargeons le nouveau profil de l’utilisateur lfs.

source ~/.bash_profile

Entrons à présent dans le vif du sujet. Nous allons déballer les archives et construire une chaîne de compilation croisée. C’est assez difficile à comprendre, mais il faut faire un effort parce que ce concept est important. Tout d’abord, qu’est-ce qu’un compilateur? Eh bien, il s’agit d’un outil de programmation informatique qui transforme un code source écrit par un être humain dans un langage de haut niveau, en un code binaire exécutable par une machine. En ce qui concerne la chaîne de compilation croisée, le chapitre du manuel censé fournir des explications claires et précises sur ce concept est, je suis désolé de le dire, absolument incompréhensible! J’ai donc préféré consulter Wikipédia. L’encyclopédie en ligne nous explique qu’une chaîne de compilation croisée est construite pour fonctionner sur une machine hôte, mais les programmes qu’elle va compiler seront installés sur un autre ordinateur qualifié de machine-cible.

Voici les éléments qui constituent une chaîne de compilation. Je cite Wikipédia:

binutils : Une collection d’utilitaires utilisés pour le traitement des fichiers binaires. Ce paquetage contient notamment l’assembleur qui transforme le pseudo-code généré par la compilation en instructions comprises par le processeur cible, et l’éditeur des liens pour lier les bibliothèques utilisées par un programme.

gcc : les compilateurs C et C++ de la collection.

glibc : La bibliothèque C du système utilisée pour les appels au noyau et le traitement des processus de bas-niveau.

Avant de débuter la compilation, nous allons déclarer la variable d’environnement suivante.

export MAKEFLAGS=-j`nproc --all`

Elle retourne le nombre de processeurs présents sur l’ordinateur et réduit le temps de compilation en effectuant un make parallèle.

Construisons notre chaîne de compilation croisée. Pour ce faire, déplaçons-nous tout d’abord dans le répertoire /mnt/lfs/sources.

cd /mnt/lfs/sources

Le processus de compilation es toujours le même. Nous commençons par décompresser l’archive tar.xz ou tar.gz et nous nous déplaçons dans le répertoire nouvellement créé.

tar -xf binutils-2.37.tar.xz
cd binutils-2.37

Ce n’est pas toujours le cas mais pour ce paquet, nous devons créer un répertoire build et nous déplacer à l’intérieur.

mkdir -v build
cd build

Nous préparons la compilation.

../configure --prefix=/mnt/lfs/tools \
    --with-sysroot=/mnt/lfs          \
    --target=$LFS_TGT                \
    --disable-nls                    \
    --disable-werror

Nous compilons et nous installons le paquet selon les instructions du manuel.

make $MAKEFLAGS
make install -j1

Ensuite, nous revenons dans le répertoire /mnt/lfs/sources. Comme nous étions dans /mnt/lfs/sources/binutils-2.37/build, nous devons entrer cette commande.

cd ../..

Enfin, après nous être connectés en root, nous supprimons le répertoire binutils-2.37 (pas l’archive binutils-2.37.tar.xz!) et nous nous connectons de nouveau en tant qu’utilisateur lfs.

su
rm -r binutils-2.37
exit

Nous enchaînons sur les paquets suivants en utilisant le même process. Nous effectuons cette opération pour :

La suite des festivités dans un prochain article!

Linux From Scratch (partie 1)

Linux From Scratch signifie Linux à partir de rien. Créé par Gerard Beeskamp, un informaticien néerlandais, ce projet pédagogique détaille le process de compilation et d’installation de tous les paquets nécessaires à la construction d’un système d’exploitation Linux léger, sécurisé et très personnalisé. Ici, pas besoin de démarrer sur une clé USB d’installation. Le seul prérequis est que l’ordinateur « hôte » soit équipé d’une distribution Linux sur laquelle nous allons nous greffer avant de nous en détacher pour voler de nos propres ailes.

J’ai décidé de me lancer dans l’aventure et de publier plusieurs articles pour vous narrer mes péripéties. Je suis en plein chantier. Cela avance plutôt bien puisque je me trouve déjà dans l’environnement chroot, mais ce n’est pas terminé. J’ai essuyé plusieurs échecs. J’aime même été obligé de réinstaller ma distribution Linux Mint suite à une manipulation hasardeuse.

Linux From Scratch est un projet exigeant. Pour en venir à bout, il est nécessaire de maîtriser la ligne de commande. cd, ls, mount, mkdir sont des termes qui doivent déjà vous parler. Si ce n’est pas le cas, il est préférable de s’arrêter là. En outre, il est impératif d’avoir de bonnes connaissances dans le domaine des distributions Linux. Si vous êtes capables d’installer Ubuntu, c’est très bien, mais je doute que cela soit suffisant. Il faut au moins maîtriser l’installation d’Archlinux. Vous l’aurez compris, ce projet n’est pas fait pour les débutants.

Sur quelle base construire un système LFS

La dénomination Linux à partir de rien est quelque peu exagérée. Pour construire notre LFS, nous allons nous appuyer sur une autre distribution Linux surnommée le système hôte. Nous en aurons besoin pour partitionner le disque dur et télécharger les sources. Ce peut être une Debian, une Ubuntu, une Fedora… Peu importe. Personnellement, je tourne sous Linux Mint. Nous allons, d’une certaine manière, parasiter le système hôte pour nous en détacher en cours de route et bâtir une distribution indépendante. Parasiter n’est peut-être pas le bon terme. Disons que le système hôte va tenir le rôle d’incubateur ou d’utérux, si je puis me permettre d’utiliser ce néologisme! Pour ce faire, il est nécessaire que certains paquets soient déjà installés sur la distribution hôte. Voici un script que nous pouvons lancer dans un terminal et qui nous confirmera que c’est bien le cas.

Toute la difficulté réside dans le fait que le processus est long et qu’une boulette est vite arrivée. Nous basculons de l’utilisateur hôte vers l’utilisateur root. Puis, nous nous connectons en tant qu’utilisateur lfs avant d’entrer dans le chroot en tant que root! Nous déclarons et manipulons des variables d’environnement qui, et là je parle en connaissance de cause, peuvent endommager voire détruire votre système hôte si elles sont mal définies. C’est la raison pour laquelle, contrairement à la documentation officielle, je me refuse à créer la variable ci-dessous. Je préfère travailler avec le chemin absolu.

LFS=/mnt/lfs

Il faut également appréhender, même de manière abstraite, des principes telles que la compilation croisée ou le chroot. Le point de montage de la partition qui hébèrge Linux From Scratch est /mnt/lfs. Lorsque nous allons chrooter dans le nouveau système, /mnt/lfs deviendra la racine de ce dernier, c’est-à-dire /. La construction des outils de compilation demande une grande vigilance. C’est la partie la plus délicate et la moindre erreur empêchera votre système de fonctionner.

Le partitionnement

Avant toute chose, connectez-vous en root. Pour construire le système LFS, il faut créer une partition de 35GB qui lui sera dédiée. Ma partition est /dev/sda4. Je l’ai créée avec Gparted. et je l’ai formatée en ext4.

mkfs.ext4 /dev/sda4

Mon répertoire personnel se trouve sur une partition qui existe déjà : /dev/sda3. Voici le partitionnement de mon disque dur avec les différents points de montage:

Ensuite, il faut créer le répertoire /mnt/lfs pour y monter la partition /dev/sda4.

mkdir -vp /mnt/lfs
mount /dev/sda4 /mnt/lfs

Puis, nous créons le répertoire qui va accueillir toutes les archives des paquets à télécharger. Nous lui donnons les droits d’écriture et sticky. Ce dernier terme signifie que même si de nombreux utilisateurs peuvent écrire dans un fichier, seul le propriétaire du répertoire peut supprimer ce fichier.

mkdir -vp /mnt/lfs/sources
chmod -v a+wt $LFS/sources

Ensuite, nous téléchargeons les sources. Pour ce faire, nous copions le contenu de cette page et nous le collons dans un fichier nommé wget-list.

wget --input-file=wget-list\
--continue\
--directory-prefix=/mnt/lfs/sources

C’est le moment de vérifier si les archives ont été correctement téléchargées. Pour effectuer cette opération, nous créons le fichier md5sums dans lequel nous rajoutons ces instructions. Puis, nous exécutons les lignes ci-dessous. Le fichier md5sums doit être au préalable déplacé dans le répertoire /mnt/lfs/sources.

mv md5sums /mnt/lfs/sources
pushd /mnt/lfs/sources
md5sum -c md5sums
popd

À ce stade, nous créons différents répertoires nécessaires à la construction de notre système LFS. Pour la version 32-bits, supprimez lib64. Le compilateur croisé sera installé dans le répertoire /mnt/lfs/tools car il doit impérativement être séparé des autres programmes.

mkdir -pv /mnt/lfs/{etc,var,lib64,tools} /mnt/lfs/usr/{bin,lib,sbin}
for i in bin lib sbin
do
  ln -sv usr/$i $LFS/$i
done

Création de l’utilisateur lfs qui devient propriétaire récursif de tout le répertoire /mnt/lfs. Pour la version 32-bits, supprimer lib64.

groupadd lfs
useradd -s /bin/bash -g lfs -m -k /dev/null lfs
passwd lfs
chown -v lfs /mnt/lfs/{usr{,/*},lib,var,etc,bin,sbin,tools,lib64,sources}

Le fichier /etc/bash.bashrc est renommé et rendu inactif pour éviter de fâcheuses interactions avec l’environnement hôte.

[ ! -e /etc/bash.bashrc ] || mv -v /etc/bash.bashrc /etc/bash.bashrc.NOUSE

Nous ouvrons un shell de connexion pour l’utilisateur lfs.

su - lfs

Voilà pour cette première partie. La suite des festivités fera l’objet d’un prochain article.