Booter Linux

Je vais tenter de décrire dans ce document les fichiers impliqués dans la phase de boot d'un système Linux, et ce juste après le chargement du noyau. Ces fichiers correspondent, pour ceux qui aiment les analogies, aux fichiers AUTOEXEC.BAT et CONFIG.SYS d'un PC sous MS-DOS/Windows, bien que certains voient les fichiers *rc des shells comme étant l'équivalent UNIX du fichier AUTOEXEC.BAT.

Ma distribution de référence est la RedHat 4.2. Même si vous employez une autre distribution, vous ne devriez pas avoir trop de problèmes pour comprendre le fonctionnement général. Les exemples donnés ici ne sont que des exemples, et votre système peut varier en fonction de la distribution que vous avez, ainsi que sa version.

Les run levels

Un run level peut être vu comme une configuration de contexte d'exploitation bien particulier, c'est-à-dire un ensemble de processus qui doivent être présent dans ce run level, et d'autres processus qui doivent impérativement être tués.

À la fin de la séquence de boot, le kernel va exécuter la commande /bin/init, qui va se charger de lancer certains services nécessaires (c'est-à-dire de placer le système dans un run level particulier). La première chose que cette commande va faire, est de scanner le fichier /etc/inittab. Ce fichier contient, entre autres, la définition du run level par défaut (cherchez la ligne qui contient initdefault)

Il y a différents run levels, qui correspondent chez moi à :

La fonction principale de /bin/init est de mettre le système dans un run level particulier, avant de rendre la main à l'utilisateur. Par exemple, chez moi, le run level 3 correspond chez moi au mode multi-utilisateur, et le 5 au même mode, mais avec démarage de X-Window.

Un conseil : n'allez pas mettre 0 ou 6 comme run level : dès le boot, votre système se bloquerait, et vous devriez alors passer par la bidouille pour le restaurer.

Enfin, /bin/init peut être utilisé pour changer le run level actuel : un petit "init 6" mettra le système dans le run level 6 (et donc la machine reboote).

/etc/inittab

Les entrées du fichier /etc/inittab ont la syntaxe suivante :

        id:rstate:action:process

id est un identificateur, formés de deux caractères.

rstate est une suite de numéros de run level. Ces numéros indiquent dans quel run level on peut trouver ces processus. Si rstate vaut "1245", le process devra être tué si le run level devient 0, 3 ou 6. Suivant la valeur de action, le process sera lancé en debut de session (once), sera relancé s'il meurt (respawn), ...

process sera n'importe quelle commande shell valide (qui peut être lancée par 'exec') .

Un petit exemple : si vous êtes dans le run level 5 (mode multi-utilisateur avec X Window), essayez donc de tuer le process xdm. Il se relance automatiquement, ce qui est normal, vu que la ligne correspondante dans /etc/inittab est :

    x:5:respawn:/usr/bin/X11/xdm -nodaemon

Dès qu'il est tué (et tant qu'on est dans le run level 5), il doit être relancé. Si vous modifiez le fichier /etc/inittab,  vous pouvez demander à init de le relire : "init q". Sans cela, tout changement ne sera pris en compte que lors du boot suivant.

Remarquez aussi que lors de l'initialisation de la machine, un script est lancé : /etc/rc.d/rc.sysinit. Il contient les commandes pour mounter les partitions swap, vérifier l'intégrité des partitions (fsck),  mounter les partitions non NFS, lancer le kerneld, ... Ce script n'est lancé qu'une seule fois, juste avant que init ne mette le système dans le run level correct. Pour cela, init vérifie l'entrée de /etc/inittab contenant le mot initdefault.Ensuite, il va lancer les commandes nécessaires pour faire passer le système dans le run level adéquat. Par exemple, chez moi, le run level par défaut est le 5. Dans mon fichier /etc/inittab, j'ai la ligne suivante :

        l5:5:wait:/etc/rc.d/rc 5

C'est-à-dire qu'init va lancer, lorsqu'il passe dans le run level 5, la commande "/etc/rc.d/rc 5". Le script /etc/rc.d/rc est générique,  c'est-à-dire que le traitement de chaque run level est le même. Ce traitement est défini dans la section suivante.

Je voudrais encore rajouter un petit commentaire par rapport aux run levels : on peut trouver des entrées dans /etc/inittab qui contiennent dans le champ rstate les valeurs a, b ou c. Il ne s'agit pas de nouveaux run levels, mais de pseudo run levels : ils permettent d'exécuter certaines commandes. Un petit "init a" va exécuter toutes les commandes ayant a dans le champ rstate.

Le répertoire rc.d

Le répertoire contenant les scripts des différents run levels est /etc/rc.d. On y trouve certains scripts : rc, rc.sysinit, rc.local, ainsi que des répertoires : init.d, rc0.d, ... rc6.d. Le répertoire rc2.d contient tous les scripts correspondants au run level 2. Pour chacun des répertoires associé à un runlevel, on trouve une collection de scripts, dont la syntaxe est [SK]nn<nom de script>. Par exemple, dans mon répertoire rc2.d, on trouve les fichiers suivants :

    K20nfs
    K40snmpd
    K90nfsfs
    S01keytable
    S10network
    S30syslog
    S40cron
    S40portmap
    S45pcmcia
    S50inet
    S60lpd.init
    S60sendmail
    S85gpm
    S99local
 
Le changement de run level est fait de manière simple : on tue les process qui ne doivent pas s'y trouver, et on lance les services présents dans ce run level.
Les scripts commencant par un K (les K-scripts) sont les scripts appelés pour tuer des processus : K20nfs est utilisé pour arrêter le service NFS. Les scripts commencant par un S (les S-scripts) sont les scripts qui lancent des services : S01keytable est le script qui va charger la keytable correspondant à mon clavier.

Vous aurez remarqué que les scripts sont aussi formés d'un numéro. Ce numéro est utilisé pour séquencer (ordonner) leur lancement. Ainsi, dans l'exemple ci-dessus, lors du lancement des S-scripts, S01keytable sera lancé avant S10network, lui-même avant S30syslog, ... Notez qu'on peut avoir deux scripts ayant le même numéro : voyez S60lpd.init, et S60sendmail. En fait, pour simplifier le tout, il suffit de se dire que les scripts sont exécutés dans l'ordre alphabétique.

Une petite finesse : il y a, en plus des répertoires rc?.d, un répertoire init.d. C'est dans ce répertoire que sont réellement stockés les scripts des répertoires rc?.d. Ces derniers ne contiennent que des liens symboliques. Ainsi, /etc/rc.d/rc1.d/K90nfs et /etc/rc.d/rc2.d/K23nfs pointent tous deux vers le même fichier, à savoir /etc/rc.d/init.d/nfs.

Encore plus fort : un K-script et un S-script peuvent tous deux pointer vers le même fichier, et avoir des comportements différents. En fait, un script est appelé en lui passant un paramètre, soit "start" s'il s'agit d'un S-script, soit "stop" (le 'K' est celui de 'Kill' : tuer) s'il s'agit d'un K-script. En fonction de ce paramètre, le script réagit différemment :
/etc/rc.d/init.d/nfs, appelé avec le paramètre "start", va lancer le service NFS, tandis que le même script, appelé avec le paramètre "stop", arrêtera ce service :

        # See how we were called.
        case "$1" in
        start)
                # Start daemons.
                echo -n "Starting NFS services: "
                daemon rpc.mountd
                daemon rpc.nfsd
                echo
                touch /var/lock/subsys/nfs
                ;;
          stop)
                # Stop daemons.
                echo -n "Shutting down NFS services: "
                killproc rpc.mountd
                killproc rpc.nfsd
                echo
                rm -f /var/lock/subsys/nfs
                ;;
          *)
                echo "Usage: nfs {start|stop}"
                exit 1
        esac

Enfin, dans chaque run level, on trouve (en dernier dans l'ordre alphabétique) un script lançant les applications spécifiques à la machine (c'est un pointeur vers le fichier /etc/rc.d/rc.local). C'est de préférences dans ce fichier là qu'il faut mettre toutes les commandes spécifiques à tous les run levels (comme par exemple la gestion du clavier, si elle n'est pas lancée dans un autre script).

Remerciements

Un grand merci à Jean-Pierre Florisoone, ainsi qu'à Nat Makarévitch pour les relectures et les conseils.