Gentoo Logo

[ << ] [ < ] [ Sommaire ] [ > ] [ >> ]


4. Les scripts d'initialisation

Table des matières :

4.a. Les niveaux d'exécution

Démarrer votre système

Quand vous démarrez votre système, vous voyez beaucoup de texte défiler à l'écran. Vous remarquerez sans doute que ce texte est le même à chaque démarrage. La séquence d'actions qui se déroule devant vos yeux s'appelle la séquence de démarrage et elle est définie de façon plus ou moins statique.

D'abord, votre chargeur de démarrage charge l'image du noyau que vous avez définie dans son fichier de configuration et ensuite, il exécute ce noyau. Ce dernier s'initialise, démarre les tâches spécifiques au noyau et lance le processus init.

Ce processus monte les systèmes de fichiers définis dans /etc/fstab et exécute quelques scripts placés dans le répertoire /etc/init.d qui, à leur tour, démarrent les services nécessaires au bon fonctionnement du système.

Finalement, quand tous les scripts ont été exécutés, init active les terminaux (en général, les consoles virtuelles que vous obtenez avec les touches Alt-F1, Alt-F2, etc.) et attache un processus appelé agetty à chacun. Ce processus vous permet de vous identifier sur ces terminaux avec login.

Les scripts d'initialisation

En fait, init n'exécute pas les scripts du répertoire /etc/init.d n'importe comment. De plus, il n'exécute pas non plus tous les scripts, mais seulement ceux qui doivent l'être. Les scripts à exécuter sont définis dans /etc/runlevels.

Le processus init exécute d'abord les scripts de /etc/init.d vers lesquels un lien symbolique existe dans /etc/runlevels/boot. Les scripts sont généralement exécutés par ordre alphabétique, mais certains contiennent des dépendances qui indiquent quels scripts doivent être exécutés en premier.

Quand tous les scripts liés dans /etc/runlevels/boot ont été exécutés, init poursuit avec ceux liés dans /etc/runlevels/default. Ici aussi, les scripts sont généralement exécutés par ordre alphabétique, sauf quand ils contiennent des informations sur des dépendances qui spécifient une séquence d'exécution particulière.

Comment init fonctionne-t-il ?

Évidemment, init ne décide pas tout seul de ce qu'il doit faire. Il a besoin d'un fichier de configuration qui lui indique quelles actions il doit effectuer. Ce fichier est /etc/inittab.

Dans la séquence de démarrage que nous venons d'expliquer, nous avons dit que la première action de init était de monter les systèmes de fichiers. La ligne du fichier /etc/inittab qui provoque cela est la suivante :

Exemple de code 1 : La ligne d'initialisation du système dans /etc/inittab

si::sysinit:/sbin/rc sysinit

En fait, cette ligne indique à init qu'il doit exécuter /sbin/rc sysinit pour initialiser le système. C'est le script /sbin/rc qui fait vraiment le travail d'initialisation et pas init qui ne fait que déléguer les tâches.

Ensuite, init exécute tous les scripts vers lesquels un lien symbolique est défini dans /etc/runlevels/boot. La ligne suivante provoque cela :

Exemple de code 2 : L'initialisation du système, suite

rc::bootwait:/sbin/rc boot

Encore une fois, le script rc fait le travail. Remarquez que l'option boot passée au script rc correspond au nom du sous-répertoire qui se trouve dans /etc/runlevels.

Ensuite, init lit son fichier de configuration pour savoir quel runlevel il doit exécuter (N.D.T. : un « runlevel », ou niveau d'exécution, correspond à l'état dans lequel il faut amener la machine). La ligne suivante définit le niveau d'exécution :

Exemple de code 3 : La ligne initdefault

id:3:initdefault:

Dans ce cas (la majorité des utilisateurs de Gentoo sont dans ce cas), le niveau d'exécution est le numéro 3. Avec ce numéro, init trouve ce qu'il doit exécuter pour lancer le niveau d'exécution 3 :

Exemple de code 4 : Les définitions des niveaux d'exécution

l0:0:wait:/sbin/rc shutdown
l1:S1:wait:/sbin/rc single
l2:2:wait:/sbin/rc nonetwork
l3:3:wait:/sbin/rc default
l4:4:wait:/sbin/rc default
l5:5:wait:/sbin/rc default
l6:6:wait:/sbin/rc reboot

La ligne qui définit le niveau 3 utilise à nouveau le script rc pour démarrer les services, cette fois avec le paramètre default. Remarquez que, encore une fois, le paramètre correspond au nom du sous-répertoire dans /etc/runlevels.

Quand le script rc a terminé, init trouve la liste des consoles virtuelles à activer et quelles commandes il doit utiliser dans son fichier de configuration :

Exemple de code 5 : La définition des consoles virtuelles

c1:12345:respawn:/sbin/agetty 38400 tty1 linux
c2:12345:respawn:/sbin/agetty 38400 tty2 linux
c3:12345:respawn:/sbin/agetty 38400 tty3 linux
c4:12345:respawn:/sbin/agetty 38400 tty4 linux
c5:12345:respawn:/sbin/agetty 38400 tty5 linux
c6:12345:respawn:/sbin/agetty 38400 tty6 linux

Qu'est-ce qu'un niveau d'exécution ?

Vous avez constaté que init numérote les niveaux d'exécution qu'il doit activer. Un niveau d'exécution définit un état dans lequel votre système se trouve et contient les scripts nécessaires pour entrer dans ou quitter cet état.

Dans Gentoo, sept niveaux d'exécution sont définis :trois internes et quatre définis par l'utilisateur. Les niveaux d'exécution internes sont sysinit, shutdown et reboot et sont utilisés respectivement pour initialiser, éteindre et redémarrer le système.

Les niveaux d'exécution définis par l'utilisateur sont ceux qui correspondent à un sous-répertoire dans /etc/runlevels : boot, default, nonetwork et single. Le niveau d'exécution boot est utilisé pour démarrer tous les services système utilisés par les autres niveaux d'exécution. Les autres niveaux d'exécution se différencient par les services qu'ils activent : default est utilisé en temps normal, nonetwork est utilisé quand aucune connexion réseau n'est souhaitée et single est utilisé pour résoudre d'éventuels problèmes du système.

Utiliser les scripts d'initialisation

Les scripts que rc exécute sont appelés des scripts d'initialisation. Chaque script peut être exécuté avec les options start, stop, restart, pause, zap, status, ineed, iuse, needsme, usesme ou broken.

Pour démarrer, arrêter ou relancer un service (et les autres services nécessaires éventuels), utilisez start, stop et restart.

Exemple de code 6 : Démarrer postfix

# /etc/init.d/postfix start

Note : Seuls les services qui ont besoin du service spécifié sont arrêtés ou redémarrés. Les services qui l'utilisent ne sont pas affectés.

Pour stopper un service sans toucher aux services qui l'utilisent, utilisez l'option pause :

Exemple de code 7 : Stopper postfix sans toucher aux services qui l'utilisent

# /etc/init.d/postfix pause

Pour afficher le statut d'un service (démarré, arrêté, en pause), utilisez l'option status :

Exemple de code 8 : Afficher le statut du service postfix

# /etc/init.d/postfix status

Si le système affirme qu'un service est actif, mais que vous savez qu'il ne l'est pas, utilisez l'option zap pour réinitialiser son statut à « arrêté ».

Exemple de code 9 : Réinitialiser le statut de postfix

# /etc/init.d/postfix zap

Vous pouvez aussi afficher les services dont un service a besoin avec les options iuse ou ineed. Avec l'option ineed, les services réellement nécessaires sont affichés. Avec iuse, ce sont les services qui peuvent être utilisés sans être indispensables qui sont affichés.

Exemple de code 10 : Afficher la liste des services dont Postfix a besoin

# /etc/init.d/postfix ineed

De la même façon, vous pouvez afficher la liste des services qui ont besoin (needsme) ou qui utilisent (usesme) un service particulier :

Exemple de code 11 : Afficher la liste des services qui ont besoin de Postfix

# /etc/init.d/postfix needsme

Enfin, vous pouvez aussi demander la liste des services requis qui manquent :

Exemple de code 12 : Afficher la liste des services manquants dont Postfix a besoin

# /etc/init.d/postfix broken

4.b. Utiliser rc-update

Qu'est-ce que rc-update ?

Gentoo construit un arbre de dépendances pour déterminer l'ordre d'exécution des services. Cela est loin d'être trivial et nous avons donc créé des outils qui facilitent l'administration des niveaux d'exécution et des scripts d'initialisation.

La commande rc-update permet d'ajouter ou d'enlever un script d'un niveau d'exécution. Cette commande utilise automatiquement le script depscan.sh qui reconstruit l'arbre des dépendances.

Ajouter et enlever des services

Vous avez déjà ajouté des scripts d'initialisation au niveau d'exécution « default » pendant l'installation de Gentoo. Vous ignoriez alors la signification de « default », mais maintenant, vous la connaissez. Le script rc-update a besoin d'un second argument qui spécifie l'action à effectuer : add, del ou show pour respectivement ajouter, supprimer ou afficher.

Pour ajouter ou supprimer un service, ajoutez simplement add ou del à la commande rc-update et spécifiez ensuite le nom du script d'initialisation et le niveau d'exécution. Par exemple :

Exemple de code 13 : Supprimer Postfix du niveau d'exécution « default »

# rc-update del postfix default

La commande rc-update show affiche la liste des scripts d'initialisation disponibles et les niveaux d'exécution dans lesquels ils ont été ajoutés :

Exemple de code 14 : Afficher la liste des scripts d'initialisation

# rc-update show

4.c. Configurer les services

Pourquoi encore configurer ?

Les scripts d'initialisation peuvent être complexes. Il vaut donc mieux éviter que les utilisateurs ne doivent les modifier. Cela évite bien des problèmes. Cependant, les services ont parfois besoin d'être configurés ou de recevoir certaines options.

Une autre raison pour séparer les scripts de leur configuration est que cela vous permet de mettre à jour les scripts sans que leur configuration ne soit perdue.

Le répertoire /etc/conf.d

Gentoo offre un système facile pour configurer les services. Chaque script d'initialisation qui peut être configuré a un fichier de configuration dans le répertoire /etc/conf.d. Par exemple, le script d'initialisation d'apache2 (/etc/init.d/apache2) a un fichier de configuration /etc/conf.d/apache2 qui contient les options à passer au serveur Apache 2 quand ce dernier est lancé.

Exemple de code 15 : Variables définies dans /etc/conf.d/apache2

APACHE2_OPTS="-D PHP4"

Un tel fichier de configuration ne contient que des définitions de variables (tout comme /etc/make.conf), ce qui permet de configurer facilement un service. Cela permet aussi de fournir des explications sur ces options sous forme de commentaires.

4.d. Écrire un script d'initialisation

Dois-je faire cela ?

Non. Rédiger un script d'initialisation n'est généralement pas nécessaire puisque Gentoo fournit des scripts complets pour tous les services supportés. Cependant, si vous avez installé un service sans l'aide de Portage, vous devrez sans doute écrire un tel script.

N'utilisez pas le script fourni avec le logiciel à moins qu'il ne soit écrit spécifiquement pour Gentoo, car les scripts d'initialisation de Gentoo ne sont pas compatibles avec ceux des autres distributions.

Structure

La structure de base d'un script d'initialisation est décrite ci-dessous.

Exemple de code 16 : Structure de base d'un script d'initialisation

#!/sbin/runscript

depend() {
  (Information sur les dépendances)
}

start() {
  (Commandes à exécuter pour démarrer le service)
}

stop() {
  (Commandes à exécuter pour arrêter le service)
}

restart() {
  (Commandes à exécuter pour redémarrer le service)
}

La partie start() est indispensable, les autres sont facultatives.

Dépendances

Il existe deux types de dépendances : use et need. Comme mentionné précédemment, la dépendance need est plus stricte que use. Vous devez faire suivre le type de dépendance par le nom du service dont votre service dépend, ou par une dépendance virtuelle.

Une dépendance virtuelle est une dépendance qui peut être satisfaite par plusieurs services différents. Par exemple, votre service pourrait dépendre du système de journalisation qui peut être fourni par plusieurs services différents (metalogd, syslog-ng, sysklogd...) Étant donné que votre service ne peut pas dépendre de tous ces services (on ne peut installer qu'un seul système de journalisation), nous avons défini une seule dépendance virtuelle que chacun de ces services satisfait.

Jetons un œil aux dépendances du service postfix.

Exemple de code 17 : Dépendances de Postfix

depend() {
  need net
  use logger dns
  provide mta
}

Comme vous pouvez le voir, postfix :

  • a besoin du service virtuel net qui est fourni par /etc/init.d/net.eth0, par exemple ;
  • utilise un système de journalisation (service virtuel logger) qui est fourni par /etc/init.d/syslog-ng, par exemple ;
  • utilise le service (virtuel) dns qui est fourni par /etc/init.d/named, par exemple ;
  • fournit le service virtuel mta qui indique qu'un serveur de courrier est disponible.

Ordonner la séquence d'exécution

Dans certains cas, vous voudrez peut-être démarrer un service avant ou après un autre, pour autant que cet autre service soit disponible. Notez qu'il ne s'agit plus d'une dépendance, mais simplement d'une demande de lancement de services dans un ordre défini au sein d'un même niveau d'exécution. Pour définir une séquence d'exécution, utilisez les mots-clefs before ou after.

Voyez, par exemple, le service portmap :

Exemple de code 18 : La fonction depend() du service Portmap

depend() {
  need net
  before inetd
  before xinetd
}

Vous pouvez aussi remplacer le nom de service par une étoile ("*") pour spécifier tous les services d'un niveau d'exécution, mais cela n'est pas recommandé.

Exemple de code 19 : Lancer un script avant tous les autres dans un niveau d'exécution

depend() {
  before *
}

Si votre service doit écrire sur des disques locaux, il aura besoin du localmount. S'il place quelque chose dans /var/run, tel un fichier .pid, alors il devra démarrer après bootmisc :

Exemple de code 20 : Exemple de fonction depend()

depend() {
  need localmount
  after bootmisc
}

Fonctions standard

En plus de la fonction depend(), vous devez définir la fonction start() qui doit contenir les commandes nécessaires pour activer le service. Il est conseillé d'utiliser les fonctions ebegin et eend pour afficher des messages à l'écran et ainsi informer l'utilisateur que le service démarre.

Exemple de code 21 : Exemple de fonction start()

start() {
  ebegin "Starting my_service"
  start-stop-daemon --start --exec /chemin/vers/mon_service \
  --pidfile /chemin/vers//mon_fichier_pid
  eend $?
}

Les options --exec et --pidfile devraient être utilisées dans les fonctions start et stop. Si le service ne crée pas de fichier .pid, alors utilisez --make-pidfile, si possible, bien que vous devriez le tester pour en être sûr. Dans le cas contraire, n'utilisez pas de fichier .pid. Vous pouvez aussi ajouter --quiet aux options start-stop-daemon, bien que cela soit déconseillé à moins que le service soit extrêmement verbeux. En effet, utiliser --quiet peut cacher des informations de débogage utiles si le démarrage du service échoue.

Note : Assurez-vous que --exec appelle effectivement un service et pas simplement un script shell qui lance des services (c'est ce que le script init est censé faire).

Vous trouverez plus d'exemples de fonctions start() dans les sources des scripts d'initialisation, localisés dans le répertoire /etc/init.d.

Vous pouvez aussi définir les fonctions facultatives stop() et restart() pour respectivement arrêter et relancer un service, mais Gentoo est capable de s'en passer si vous avez utilisé la commande start-stop-daemon.

Bien que vous ne devriez pas créer de fonction stop(), en voici quand même un exemple :

Exemple de code 22 : Exemple de fonction stop()

stop() {
  ebegin "Arrêt de mon_service"
  start-stop-daemon --stop --exec /chemin/vers/mon_service \
    --pidfile /chemin/vers/mon_fichier_pid
  eend $?
}

Si votre service exécute un script (Bash, Python ou Perl par exemple) dont le nom change par la suite (par exemple, toto.py devient toto), il faut alors ajouter l'option --name à la commande start-stop-daemon. Vous devez y spécifier le nom du script après changement. Dans cet exemple, un service démarre toto.py dont le nom devient toto :

Exemple de code 23 : Un service qui lance le script toto

start() {
  ebegin "Démarrage de mon_script"
  start-stop-daemon --start --exec /chemin/vers/mon_script \
  --pidfile /chemin/vers/mon_fichier_pid --name toto 
  eend $?
}

Pour de plus amples informations, un excellent manuel est disponible pour la commande start-stop-daemon :

Exemple de code 24 : Consulter le manuel de start-stop-daemon

$ man start-stop-daemon

Les scripts d'initialisation utilisent bash. Vous pouvez utiliser toutes les fonctionnalités de bash dans vos scripts.

Ajouter une option non prévue

Si vous voulez utiliser une option non prévue par nos scripts, vous devez l'ajouter à la variable opts et créer une fonction qui a le même nom. Par exemple, pour ajouter une option restartdelay :

Exemple de code 25 : Ajouter une option restartdelay

opts="${opts} restartdelay"

restartdelay() {
  stop
  sleep 3    # Temporisation de 3 secondes
  start
}

Variables de configuration d'un service

Vous ne devez rien faire de particulier pour utiliser un fichier de configuration dans /etc/conf.d : avant que votre script d'initalisation ne soit exécuté, les variables des fichiers suivants sont initialisées dans cet ordre :

  • /etc/conf.d/<votre_script>
  • /etc/conf.d/basic
  • /etc/rc.conf

De plus, si votre script fournit un service virtuel (comme net), le fichier de configuration correspondant (comme /etc/conf.d/net) sera également lu.

4.e. Modifier le comportement des niveaux d'exécution

Quel intérêt et pour qui ?

Les utilisateurs d'ordinateurs portables connaissent bien le problème : vous devez démarrer net.eth0 à la maison, mais pas lorsque vous êtes en vadrouille puis que vous n'êtes alors plus connecté à votre réseau. Vous pouvez adapter le comportement de Gentoo.

Par exemple, vous pouvez créer un second niveau d'exécution similaire au niveau « default », mais sans les options réseau. Vous pourrez ensuite sélectionner le niveau d'exécution au démarrage de votre machine.

Utiliser « softlevel »

Créez votre second niveau d'exécution similaire à « default ». Dans notre exemple, nous créons un niveau « offline ».

Exemple de code 26 : Créer le répertoire du nouveau niveau d'exécution

# mkdir /etc/runlevels/offline

Ajoutez les scripts d'initialisation à votre nouveau niveau d'exécution. Par exemple, pour copier le niveau « default » sauf le script net.eth0 :

Exemple de code 27 : Recopier les scripts d'initialisation

(Copier tous les services du niveau d'exécution default vers offline.)
# cd /etc/runlevels/default
# for service in *; do rc-update add $service offline; done
(Supprimer les services superflus du niveau d'exécution offline.)
# rc-update del net.eth0 offline
(Afficher les services du niveau d'exécution offline.)
# rc-update show offline
(Affichage partiel :)
               acpid | offline
          domainname | offline
               local | offline
            net.eth0 |

Même si net.eth0 a été retiré du niveau d'exécution offline, udev va quand même essayer de démarrer les interfaces qu'il détecte et lancer les services associés. C'est pourquoi vous devez ajouter les services réseaux que vous ne souhaitez pas voir démarrés au fichier /etc/conf.d/rc (cela est vrai pour tout autre service pouvant être lancé par udev) :

Exemple de code 28 : Désactiver un service démarré par une interface dans /etc/conf.d/rc

RC_COLDPLUG="yes"
(Ensuite, spécifiez les services que vous ne souhaitez pas voir
          démarrés automatiquement)
RC_PLUG_SERVICES="!net.eth0"

Note : Vous trouverez plus d'informations sur les services démarrés par les interfaces en consultant les commentaires du fichier /etc/conf.d/rc.

Ensuite, modifiez la configuration de votre chargeur de démarrage pour y ajouter une nouvelle option pour le niveau offline. Par exemple, pour grub, modifiez /boot/grub/grub.conf :

Exemple de code 29 : Ajouter une entrée dans le menu de démarrage

title Gentoo Linux Offline
  root (hd0,0)
  kernel (hd0,0)/kernel-2.4.25 root=/dev/hda3 softlevel=offline

Voilà, c'est terminé. Si vous redémarrez votre machine et que vous choisissez la nouvelle entrée, le niveau d'exécution offline sera utilisé au lieu du niveau default.

Utiliser « bootlevel »

Vous pouvez aussi remplacer le niveau d'exécution « boot » avec l'option bootlevel exactement de la même façon qu'avec softlevel.


[ << ] [ < ] [ Sommaire ] [ > ] [ >> ]


Imprimer

Dernière mise à jour le 2 juin 2007

Une version originale plus récente datée du 7 juillet 2007 existe.

Résumé : Gentoo fait appel à un format particulier de scripts de démarrage qui, entre autres, permet la gestion des dépendances et le support des services virtuels. Ce chapitre explique ces aspects et comment utiliser de tels scripts.

Sven Vermeulen
Auteur

Grant Goodyear
Auteur

Roy Marples
Auteur

Daniel Robbins
Auteur

Chris Houser
Auteur

Jerry Alexandratos
Auteur

Seemant Kulleen
Développeur Gentoo x86

Tavis Ormandy
Développeur Gentoo Alpha

Jason Huebel
Développeur Gentoo AMD64

Guy Martin
Développeur Gentoo HPPA

Pieter Van den Abeele
Développeur Gentoo PPC

Joe Kallar
Développeur Gentoo SPARC

John P. Davis
Correcteur

Pierre-Henri Jondot
Correcteur

Eric Stockbridge
Correcteur

Rajiv Manglani
Correcteur

Jungmin Seo
Correcteur

Stoyan Zhekov
Correcteur

Jared Hudson
Correcteur

Colin Morey
Correcteur

Jorge Paulo
Correcteur

Carl Anderson
Correcteur

Jon Portnoy
Correcteur

Zack Gilburd
Correcteur

Jack Morgan
Correcteur

Benny Chuang
Correcteur

Erwin
Correcteur

Joshua Kinard
Correcteur

Tobias Scherbaum
Correcteur

Joshua Saddler
Correcteur

Gerald J. Normandin Jr.
Relecteur

Donnie Berkholz
Relecteur

Ken Nowack
Relecteur

Lars Weiler
Contributeur

Xavier Neys
Correcteur, traducteur

Camille Huot
Traducteur

Benjamin Girault
Traducteur

Olivier Fisette
Traducteur

Olivier Roomans
Traducteur

Vincent Strubel
Traducteur

Donate to support our development efforts.

Gentoo Centric Hosting: vr.org

VR Hosted

Tek Alchemy

Tek Alchemy

SevenL.net

SevenL.net

php|architect

php|architect

Copyright 2001-2007 Gentoo Foundation, Inc. Questions, Comments? Contact us.