Cours Linux : les runlevels

I. Présentation, définition

Au démarrage ou à l’arrêt d’une machine Linux (ou Unix en général), plusieurs tâches doivent être effectuées. Ces tâches peuvent correspondre à des fonctionnalités de base (montage des partitions, chargement des périphériques, démarrage de l’interface graphique, ..) ou à des tâches plus spécifiques (lancement d’un serveur web, d’un service ssh, d’une base de données MySQL, …).

Le premier processus a être lancé sur un système Unix est le programme init (qui est le père de tous les processus existants). Son but est, entre autres, de lancer tous les autres processus nécessaires à l’utilisation d’une machine.

La gestion de tous les services installés sur une machine passe par des scripts situés dans le répertoire /etc/init.d/ . Ce répertoire contient un script par service (serveur web, gestion du réseau, l’interface graphique, le DHCP, le gestionnaire des logs, …).
Ces scripts peuvent être exécutés en leur passant un paramètre spécifique :

  • start : démarre le service

    • stop : arrête le service
    • restart : redémarre le service
    • reload : force la relecture du fichier de configuration sans arrêter le service
    • status : affiche l’état actuel du service (démarré, éteint, …)
      Par exemple, pour lancer un serveur apache, il faut exécuter cette commande : /etc/init.d/apache2 start ou pour le redémarrer : /etc/init.d/apache2 restart .
      Cette liste n’est pas exhaustive et n’est pas applicable à tous les scripts. En effet, cela dépend du script. Certains scripts ne sont pas prévus pour prendre en compte le paramètre relaod par exemple.

    Ces scripts sont donc le moyen de contrôler les différents services installés sur votre machine. Lors de l’installation d’un paquet correspondant à un service, un script est automatiquement ajouté dans ce répertoire. Bon d’accord mais quel est le rapport avec les runlevels ?

    En fait, il y a 7 runlevels différents sur un système Unix. Chacun est associé à un état de votre machine. Voici les runlevels des systèmes Debian/Ubuntu :

  • Runlevel 0 : Arrêt de la machine

    • Runlevel 1 : Mode maintenance (mono-utilisateur en ligne de commande)
    • Runlevel 2 à 5 : Mode multi-utilisateur complet avec serveur graphique si installé
    • Runlevel 6 : Redémarrage de la machine
      Vous vous en doutez, pour chaque état de la machine, il va falloir exécuter des scripts différents (par exemple, pour le runlevel 0 (l’arrêt du système), il faut arrêter tous les services de la machine. En revanche, pour le runlevel 2 (le démarrage du système), il va falloir démarrer tous les services de la machine). Vous me suivez ?

    Lorsqu’un système Unix démarre, il se place dans le runlevel 2, 3, 4 ou 5 (par défaut, le 2). Que se passe t-il donc ?
    Admettons que le système utilise le runlevel par défaut pour démarrer (le 2). Au démarrage, il va consulter le répertoire /etc/rc2.d/ . Allons voir ce que contient ce répertoire ( ls -l /etc/rc2.d/ ) :

    • […] *
    • lrwxrwxrwx 1 root root 13 2008-11-18 20:04 S16ssh -> ../init.d/ssh *
    • lrwxrwxrwx 1 root root 15 2008-12-17 19:50 S19mysql -> ../init.d/mysql *
    • lrwxrwxrwx 1 root root 14 2008-11-03 14:58 S89cron -> ../init.d/cron *
    • lrwxrwxrwx 1 root root 17 2008-11-17 19:31 S91apache2 -> ../init.d/apache2 *
    • […] *

    Voici la syntaxe d’une ligne :

    • X00service -> ../init.d/service *
    • X correspond à la lettre S ou à la lettre K. Si il y a la lettre S, le paramètre start sera passé au script /etc/init.d/service * . En revanche, si c’est la lettre K, c’est le paramètre stop qui sera passé à ce script.
    • 00 correspond à une priorité d’exécution. Le service possédant le plus petit chiffre s’exécutera en premier. Par exemple, S16ssh s’exécutera avant S89cron . (Attention : Tous les liens commençant par K s’exécuteront avant les liens commençants par un S)
      • service * correspond au au nom du service lancé (ou arrêté). Exemple : apache2, ssh, …
      • -> ../init.d/service indique que ce lien utilise le fichier /etc/init.d/service avec un paramètre. Par exemple /etc/init.d/apache2 start
        Je vous ai dit que le processus init était le père de tous les autres. Concrètement, quand une machine démarre, le noyau se charge puis passe la main à init qui va, dans un premier temps, lancer toutes les commandes du fichier
        /etc/rcS.d/ (montage des périphérques, du réseau, …) puis, il va lancer toutes les commandes situées dans le fichier /etc/rcX.d/ * , X étant le runlevel actuel (par défaut le 2).

    Vous avez compris ? Ce n’est pas difficile de toutes façons 🙂

    Bon, comme dans tout cours digne de ce nom, nous allons faire une petite pause café pour détendre un peu vos neurones :

    II. Changement du runlevel

    Sous Debian il existe un fichier /etc/inittab qui contient cette ligne :

    id:2:initdefault:

    Cela signifie que le système boot avec le runlevel 2. Pour changer le runlevel de démarrage, vous l’aurez compris, il suffit de modifier cette ligne et de mettre le numéro de votre choix à la place du 2.

    Sous Ubuntu , ce fichier n’existe pas, il faut donc utiliser le Grub (ce n’est pas la seule solution mais c’est, selon moi, la plus simple) :

  • De manière permanente : Éditez le fichier /boot/grub/menu.list. Par exemple, copiez ces lignes (qui correspondent à une ligne de votre Grub) :

    • title Ubuntu 8.04.1, kernel 2.6.24-21-eeepc *

    • root (hd0,0) *

    • kernel /boot/vmlinuz-2.6.24-21-eeepc root=UUID=8db02c66-167f-467a-a8f8-3f6ae22a70d4 ro *

    • initrd /boot/initrd.img-2.6.24-21-eeepc *

    • quiet

    • Puis collez-les en dessous en ajoutant les mots en gras :

    • title Ubuntu 8.04.1, kernel 2.6.24-21-eeepc – runlevel 3 *

    • root (hd0,0) *

    • kernel /boot/vmlinuz-2.6.24-21-eeepc root=UUID=8db02c66-167f-467a-a8f8-3f6ae22a70d4 ro 3 *

    • initrd /boot/initrd.img-2.6.24-21-eeepc *

    • quiet *

    Vous aurez désormais une ligne de plus dans votre grub au démarrage, vous pourrez la sélectionner pour booter en runlevel 3.

    • De manière temporaire : Lorsque vous démarrez, au moment du grub, appuyez sur la touche e pour éditer la ligne kernel puis ajoutez un chiffre à la fin de la ligne (chiffre qui correspondra au runlevel avec lequel vous souhaitez démarrer).
      Enfin, appuyez sur b pour démarrer. Vous démarrerez avec le runlevel indiqué précédemment.
      PS. Pour connaitre votre runlevel actuel, vous pouvez tapper dans un terminal la commande who -r .

    III. Configuration et personnalisation d’un runlevel

    Pour vous expliquer comment faire un runlevel personnalisé, nous allons prendre un exemple concret. Dans mon précédent article , je disais qu’il était préférable de démarrer un serveur sans interface graphique (bien qu’un serveur ne devrait pas être installé avec une interface graphique). Bref, nous partons du principe qu’une interface graphique est installée et qu’elle se lance par défaut à chaque démarrage.
    Nous allons donc voir comment désactiver cette interface graphique au démarrage en utilisant un runlevel personnalisé (nous allons personnaliser le runlevel 3).

    Premièrement, nous allons devoir identifier quel service sert à lancer notre interface graphique. Pour cela, nous pouvons lister les éléments contenus dans notre runlevel par défaut (le 2) : ls -l /etc/rc2.d/

  • […] *

    • lrwxrwxrwx 1 root root 20 2008-11-03 14:58 S25pulseaudio -> ../init.d/pulseaudio *
    • lrwxrwxrwx 1 root root 13 2008-11-03 14:58 S30gdm -> ../init.d/gdm *
    • lrwxrwxrwx 1 root root 17 2008-11-03 14:58 S89anacron -> ../init.d/anacron *
    • lrwxrwxrwx 1 root root 13 2008-11-03 14:58 S89atd -> ../init.d/atd *
    • lrwxrwxrwx 1 root root 14 2008-11-03 14:58 S89cron -> ../init.d/cron *
    • lrwxrwxrwx 1 root root 24 2008-12-11 16:44 S90binfmt-support -> ../init.d/binfmt-support *
    • lrwxrwxrwx 1 root root 17 2008-11-17 19:31 S91apache2 -> ../init.d/apache2 *
    • […] *

    Le fautif se trouve être S30gdm (le nombre peut varier chez vous).

    Nous allons donc devoir supprimer cette exécution. Pour ce faire, il faut exécuter ces commandes :

    update-rc.d -f gdm remove

    Cette commande va, dans un premier lieu, supprimer gdm de tous les runlevels . Nous allons pouvoir le rajouter à notre convenance :

    update-rc.d gdm start 30 2 . stop 30 0 6 .

    Grâce cette commande, nous ajoutons le démarrage de gdm avec une priorité de 30 (j’ai conservé l’ancienne) dans le runlevel 2 uniquement, puis nous l’arrêtons dans les runevels 0 et 6 (arrêt et redémarrage de la machine).
    Vous constatez que nous ne l’avons pas ajouté dans le runlevel 3, ce qui est normal car on veut un runlevel 3 sans gdm.

    Voilà, vous pouvez désormais redémarrer en runlevel 3, vous verrez que vous resterez en mode texte 🙂

    Ainsi se termine ce premier cours, j’espère qu’il vous a plu. Si vous avez d’autres sujets de cours, j’accepte avec plaisir 🙂