Page suivante Page précédente Table des matières
3. L'
initde la Red Hat.3.1 Niveaux d'exécution System V
À tout moment, votre système Linux se trouve à un niveau d'exécution donné. La distribution Red Hat en définit 7 :
- 0 : Hors service : l'alimentation peut alors être coupée dans danger
- 1 : Mode mono-utilisateur (pour administration système)
- 2 : Mode multi-utilisateurs : fonctionnement normal sans NFS (identique au niveau 3 mais sans les fonctionnalités réseau).
- 3 : Mode multi-utilisateurs : fonctionnement normal pour systèmes en réseau, partageant leurs ressources avec d'autres systèmes.
- 4 : Inutilisé
- 5 : X11
- 6 : Mise hors service et redémarrage : sert durant le redémarrage du système à partir d'un niveau de fonctionnement (2, 3, 4, 5). Le système passera ensuite au niveau 0.
Comme on peut le voir, un niveau d'exécution est donc un état d'
initet du système qui définissent quels sont les services qui s'exécutent.
Lors de la phase de démarrage,
initdoit savoir à quel niveau placer le système. Pour cela, il recherche dans le fichier/etc/inittabla ligne qui configure ce niveau par défaut :
id:3:initdefault:signifie que le système démarrera en Mode multi-utilisateurs complet. (ce serait une grosse bêtise de choisir les niveaux 0 ou 6 comme niveaux par défaut !!!).
Vous remarquerez que la sortie de la commande
psci-dessus indiquait qu'initavait démarré le système en niveau 3. Toutefois, cette fonctionnalité n'est pas disponible par défaut dans toutes les distributions : la même ligne pour une Debian aurait donné :
USER PID %CPU %MEM SIZE RSS TTY STAT START TIME COMMAND root 1 0.1 0.4 740 384 ? S 17:12 0:04 initMis nous verrons ci-dessous qu'il existe une commande permettant de connaître à la fois le niveau d'exécution courant et celui qui l'a précédé.
3.2 La commande
telinitOn peut changer de niveau d'exécution grâce à la commande
telinit(qui n'est qu'un lien surinit) :
# telinit 2placera le système en Mode multi-utilisateurs sans réseau. Bien entendu, seul l'administrateur système (
root) peut exécuter cette commande...
Si l'on consulte la page man de
telinit(c'est la même que celle d'init, on note que la première possède des options supplémentaires. Une lecture attentive nous apprend ainsi quetelinitpermet de demander àinitde passer dans un niveau n (avec n compris entre 0 et 6) : c'est ce que nous écrivions plus haut.
Mais
telinitdispose de fonctionnalités supplémentaires : il permet de demander àiniteffectuer une relecture de/etc/inittab, ce qui est pratique après une modification de ce fichier grâce à la commande
# telinit qalors, qu'on ne me parle plus de la nécessité de redémarrer sa machine après une modification des scripts de démarrage !
Il dispose aussi de plusieurs autres optionsé : toutes ont pour but d'indiquer à
initde réaliser une certaine tâche. Nous ne les traiterons pas ici et laissons le soin au lecteur curieux de lire la page de manuel.3.3 Connaître le niveau d'exécution courant
En réalité, il existe plus que 7 niveaux d'exécution : la commande
man initnous apprend en effet qu'il existe aussi les niveaux 7, 8 et 9 (non documentés) etS(ous) qui correspond au mode mono-utilisateur.La plupart des Unix utilisent une version de la commande
whoqui permet d'indiquer le niveau d'exécution courant :
# who -r . run level 3 Oct 17 18:00 3 0 SCette sortie indique que le 17 Octobre, le système est passé du niveau de fonctionnement
Sau niveau 3. Le 0 indique que ce passage s'est effectué du premier coup.Malheureusement, l'option
-rn'est pas disponible sous linux... Aussi, il faut utiliser une autre commande pour avoir cette information :
# runlevel runlevel N 2Indique que le système est au niveau 2 et qu'il n'y a pas de niveau précédent.
# telinit 3 # runlevel 2 3Ici, on est passé au niveau 3, le niveau précédent était le niveau 2.
Comme nous l'avons vu plus haut, la ligne de la commande
ps auxconcernantinitrenseigne aussi sur le niveau courant, mais pas dans toutes les distributions.3.4 Le fichier
/etc/inittabLorsqu'il démarre,
initlit le fichier/etc/inittabligne par ligne (si on modifie ce dernier, ce n'est pas la peine de rebooter comme sous MS-DOS après toute modification deCONFIG.SYSet/ouAUTOEXEC.BAT, il suffit d'envoyer un signalHUPàinitpour le forcer à le relire avec la commande
# kill -HUP 1ou
kill -s HUP 1Le fichier
/etc/inittabest un fichier texte composé de lignes de commentaires (commençant par#) et d'entrées constituées de 4 champs délimités par des deux-points, elles sont de la forme :
code:niveaux:action:processus
- «
code» est un identificateur unique pour chaque entrée, c'est soit un nombre, soit un mot-clé composé de caractères et/ou de chiffres : nous avons déjà vu «id» pour l'entrée correspondant au niveau d'exécution par défaut, il en existe d'autres.- «
niveaux» est une liste de niveaux d'exécution auxquels s'appliquera l'entrée, si cette liste est vide, cela équivaut à indiquer tous les niveaux.- «
action» précise comment doit être traiter le processus indiqué par le champ «processus» à l'entrée dans un des niveaux de la liste «niveaux». Les actions possibles sont :
- wait :
lancer le processus et attendre qu'il se termine avant de passer à l'entrée suivante d'inittab. Ce type d'entrée sert principalement à lancer les scripts d'initialisation pour chaque niveau. Exemples :
l0:0:wait:/etc/rc.d/rc 0 l1:1:wait:/etc/rc.d/rc 1 l2:2:wait:/etc/rc.d/rc 2 l3:3:wait:/etc/rc.d/rc 3 l4:4:wait:/etc/rc.d/rc 4 l5:5:wait:/etc/rc.d/rc 5 l6:6:wait:/etc/rc.d/rc 6indique qu'à l'entrée dans le niveau
n, il faut lancer le script/etc/rc.d/rc n.
- respawn :
lancer le processus et le relancer automatiquement lorsqu'il se termine. Elle est utilisée pour la gestion des terminaux. Exemples :
1:12345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2 3:2345:respawn:/sbin/mingetty tty3 4:2345:respawn:/sbin/mingetty tty4 5:2345:respawn:/sbin/mingetty tty5indique qu'à tous les niveaux multi-utilisateurs (2 à 5), la commande
mingettyêtre relancée sur les terminauxtty1àtty5lorsqu'elle se terminera (afin de pouvoir se logger, se délogger et se relogger). Pour le niveau 1 (mono-utilisateur), seul le terminaltty1sera utilisable.
- once :
lancer le processus s'il n'est pas déjà lancé, ne pas attendre qu'il soit terminé. Exemple :
ud::once:/sbin/updateindique que, quel que soit le niveau où l'on entre, l'utilitaire
updatesera actif. Il est chargé d'écrire périodiquement sur disque le contenu du cache : ne le désactivez surtout pas !
- boot :
ne lancer le processus qu'au démarrage du système et ne pas attendre qu'il se termine (le champ «
niveaux» est ignoré).
- bootwait :
idem mais attendre sa terminaison.
- initdefault :
spécifie le niveau de fonctionnement par défaut (le champ «
niveaux» est ignoré).
- sysinit :
le processus doit s'effectuer au démarrage du système, avant toute entrée d'action «
boot» ou «bootwait» (le champ «niveaux» est ignoré). Exemple :
si::sysinit:/etc/rc.d/rc.sysinit
- power... :
Les actions commençant par «
power..... » servent à gérer les dispositifs d'alimentation sauvegardée (UPS). Exemple :
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down" pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"Bien entendu, elle n'ont de sens que si l'on dispose d'équipements de ce genre.
- ctrlaltdel :
le processus sera exécuté lorsqu'init recevra le signal
SIGINT(généré par la combinaison de touchesCTRL-ALT-SUPPR). Elle sert généralement à arrêter et/ou redémarrer le système. Exemple :
ca::ctrlaltdel:/sbin/shutdown -t3 -h nowUn examen de votre
/etc/inittabvous montrera que celui-ci est divisé en un certain nombre de sections délimitées par des commentaires.
Notez, qu'à part modifier le niveau d'exécution par défaut et la commande associée à
CTRL-ALT-SUPPR, il y a peu de raisons pour lesquelles vous serez amené à modifier ce fichier.3.5 Les scripts d'initialisation de
/etc/rc.dL'étude de
/etc/inittabnous a montré qu'initlançait des programmes se trouvant dans le répertoire/etc/rc.d. Ce sont les fameux scripts d'initialisation dont nous parlions dans l'introduction. Par exemple, la ligne :
l2:2:wait:/etc/rc.d/rc 2signifie qu'
initdoit lancer le script/etc/rc.d/rcen lui passant2en paramètre à chaque fois qu'on entre dans le niveau 2 et qu'il doit attendre la terminaison de ce script avant de poursuivre.
La ligne :
si::sysinit:/etc/rc.d/rc.sysinitsignifie qu'
initdoit lancer le script/etc/rc.d/rc.sysinitlors de l'initialisation du système, quel que soit le niveau d'exécution.
Un examen de ce répertoire nous donne quelque chose comme :
# ls -l /etc/rc.d drwxr-xr-x 2 root root 1024 jui 31 19:30 init.d -rwxr-xr-x 1 root root 1593 jun 2 19:59 rc -rwxr-xr-x 1 root root 690 jun 2 19:59 rc.local -rwxrwx--- 1 news news 2083 jun 13 15:28 rc.news -rwxr-xr-x 1 root root 6697 jun 2 19:59 rc.sysinit drwxr-xr-x 2 root root 1024 jui 31 19:30 rc0.d drwxr-xr-x 2 root root 1024 jui 31 19:30 rc1.d drwxr-xr-x 2 root root 1024 jui 31 19:30 rc2.d drwxr-xr-x 2 root root 1024 jui 31 19:30 rc3.d drwxr-xr-x 2 root root 1024 jui 31 19:30 rc4.d drwxr-xr-x 2 root root 1024 jui 31 19:30 rc5.d drwxr-xr-x 2 root root 1024 jui 31 19:30 rc6.dce qui nous enseigne que ce répertoire ne contient que 4 fichiers exécutables :
rc, rc.local, rc.newsetrc.sysinit(lerc.newsn'existera peut être pas sur votre système si vous ne l'avez pas configuré comme serveur Usenet).
rc.local, comme son nom l'indique est « local » à votre machine : c'est là que vous ajouterez les commandes d'initialisation propres à votre système.rc.localest appelé en dernier, c'est-à dire après tous les autres scripts. Par défaut, sur mon système, il se contente de laisser un message indiquant la version Red Hat et celle du noyau dans le fichier/etc/issue, à partir des informations qu'il tire du système. Ce fichier, s'il existe, est affiché automatiquement avant l'invite de login.
rc.news, s'il existe, lance les démons nécessaires au serveur de news.
rc.sysinit, on l'a vu, est le script qui est lancé lors de l'initialisation du système, il sert à configurer la variable d'environnementPATHau niveau du système, à activer le swap, à configurer le nom de la machine avec la commandehostname, à lancer les commandes de vérification des systèmes de fichiers, à les monter, à activer les modules si ceux-ci sont utilisés, etc. Parcourez-le, cela vous donnera envie de connaître la syntaxe du shell...
rc, on l'a vu aussi, est appelé parinitavec un paramètre correspondant au niveau d'exécution dans lequel on entre. Ce paramètre est récupéré par le scriptrcpour former un nom de répertoire. Par exemple, l'appel/etc/rc.d/rc 2fera quercira examiner le répertoire/etc/rc.d/rc2.d. Un examen du code dercmontre qu'il exécute alors d'abord les scripts de ce répertoire dont le nom commence parK, puis ceux dont le nom commence parS. Le rôle dercest donc surtout un rôle d'aiguillage et d'exécution d'autres scripts.3.6 Les scripts d'initialisation de
/etc/rc.d/rcn.dExaminons, par exemple, le contenu du répertoire
/etc/rc.d/rc2.d, examiné par le script/etc/rc.d/rclorsqu'il est appelé parinitlorsque le système entre dans le niveau d'exécution 2 :
$ ls -l /etc/rc.d/rc2.d total 0 lrwxrwxrwx 1 root root 18 jun 12 12:02 K10pnserver -> ../init.d/pnserver lrwxrwxrwx 1 root root 15 jun 12 12:02 K15sound -> ../init.d/sound lrwxrwxrwx 1 root root 17 jun 12 12:02 K20rusersd -> ../init.d/rusersd lrwxrwxrwx 1 root root 15 jun 12 12:02 K20rwhod -> ../init.d/rwhod lrwxrwxrwx 1 root root 14 jun 12 12:00 K25innd -> ../init.d/innd lrwxrwxrwx 1 root root 14 jun 12 12:01 K50inet -> ../init.d/inet lrwxrwxrwx 1 root root 16 jun 12 12:02 K55routed -> ../init.d/routed lrwxrwxrwx 1 root root 13 jun 12 11:58 K60atd -> ../init.d/atd lrwxrwxrwx 1 root root 15 jun 12 12:00 K95nfsfs -> ../init.d/nfsfs lrwxrwxrwx 1 root root 17 jun 12 12:01 S01kerneld -> ../init.d/kerneld lrwxrwxrwx 1 root root 17 jun 12 12:00 S10network -> ../init.d/network lrwxrwxrwx 1 root root 16 jun 12 12:00 S20random -> ../init.d/random lrwxrwxrwx 1 root root 16 jun 12 12:02 S30syslog -> ../init.d/syslog lrwxrwxrwx 1 root root 15 jun 12 12:04 S40crond -> ../init.d/crond lrwxrwxrwx 1 root root 13 jun 12 12:01 S60lpd -> ../init.d/lpd lrwxrwxrwx 1 root root 18 jun 12 12:00 S75keytable -> ../init.d/keytable lrwxrwxrwx 1 root root 18 jun 12 12:02 S80sendmail -> ../init.d/sendmail lrwxrwxrwx 1 root root 13 jun 12 11:59 S85gpm -> ../init.d/gpm lrwxrwxrwx 1 root root 11 jun 12 12:00 S99local -> ../rc.localComme on le voit, il ne contient que des liens vers des fichiers du répertoire
/etc/rc.d/init.d/(saufS99local, qui pointe vers/etc/rc.d/rc.local).
Ces liens sont de deux types, ceux dont le nom commence par
K(comme Kill : arrêter), ceux dont le nom commence parS(Start : démarrer). Comme nous l'avons vu,/etc/rc.d/rcexécute en premier ceux dont le nom commence parK(en fait, il les exécute dans l'ordre dans lequel ils apparaissent avec la commandels...). L'ordre est réglé entre les liens par le biais d'une numérotation : ainsi, pour assurer que/etc/rc.d/rc.localsoit lancé en dernier, on met 99 derrière leS(ce qui suit ces 3 caractères a peu d'importance, ce lien aurait pu se nommerS99toto: tout ce qui compte, c'est l'ordre d'apparition).
Quand le système entre dans le niveau d'exécution 2,
init, par le biais de la commande/etc/rc.d/rc 2, exécute la commande/etc/rc.d/rc2.d/K10pnserver stop. Cela est réalisé par les lignes suivantes :
# Lancer d'abord les scripts KILL for i in /etc/rc.d/rc$runlevel.d/K*; do # Vérifie si le script existe [ ! -f $i ] && continue # Vérifie si le sous-système est déjà lancé subsys=${i#/etc/rc.d/rc$runlevel.d/K??} [ ! -f /var/lock/subsys/$subsys ] && \ [ ! -f /var/lock/subsys/${subsys}.init ] && continue # Arrête le sous-système $i stop doneAvec notre exemple, la variable
iprendra successivement tous les noms des fichiers/etc/rc.d/rc2.d/K*, après avoir testé que le sous-système a bien été lancé, la commande$i stoplancera le script en lui passant l'argumentstop. On pourra vérifier que le traitement des liens dont le nom commence parSsuit la même démarche sauf qu'il vérifie que le service n'est pas déjà lancé et que c'est l'argumentstartqui est passé au script.
Le but du répertoire
/etc/rc.d/rc2.d/est donc simplement d'indiquer quels sont les scripts à stopper et à lancer lorsqu'on entre dans le niveau 2. Pour stopper un service supplémentaire, il suffit de créer un lien dont le nom commence parKdans ce répertoire. Après leK, on choisi un numéro pour qu'il soit placé en bonne place, et généralement le nom du service concerné. Ce lien doit alors pointer vers le véritable script se trouvant dans/etc/rc.d/init.d.
Par exemple,
ln -s /etc/rc.d/init.d/toto /etc/rc.d/rc2.d/K12totofera qu'à la prochaine entrée en niveau 2,initarrêtera le servicetotoaprès avoir arrêté le servicepnserveret avant d'arrêter le servicesound. La même démarche s'applique pour le lancement de services supplémentaires.
On notera que Linux dispose d'interfaces graphiques permettant de « faciliter » ces ajouts/suppressions : l'outil
tksysvde Red Hat, les outils graphiques de KDE et Gnome, Linuxconf.
Les répertoires
/etc/rc.d/rc0.det/etc/rc.d/rc6.dsont particuliers puisqu'ils correspondent respectivement à l'entrée dans le niveau de mise hors service et dans le niveau de redémarrage. L'examen du premier vous montrera qu'il ne comporte que de liensKet un seul lienS:S00halt. C'est logique, car la mise hors service doit commencer par arrêter tous les services en cours, puis lancer la routine d'arrêt du système. De même,rc6.dcontient des liensKet un lien vers le script de redémarrage (S00reboot).
En fait, cette méthode peut sembler lourde alors qu'elle est finalement d'une simplicité à toute épreuve : à part
rc.local, tous les scripts sont regroupés dans le répertoire/etc/rc.d/init.det on décide dans le répertoire associé au niveaun(/etc/rc.d/rcn.d) des scripts qu'il faut lancer et de ceux qu'il faut arrêter...3.7 Les scripts d'initialisation de
/etc/rc.d/init.dExaminons le contenu de ce répertoire :
$ ls -l /etc/rc.d/init.d total 38 -rwxr-xr-x 1 root root 884 mai 5 18:19 atd -rwxr-xr-x 1 root root 883 mai 6 01:29 crond -rwxr-xr-x 1 root root 3375 jun 2 19:59 functions -rwxr-xr-x 1 root root 1073 mai 8 05:59 gpm -rwxr-xr-x 1 root root 1351 jun 2 19:59 halt -rwxr-xr-x 1 root root 1509 mai 6 01:25 inet -rwxr-x--- 1 root root 1510 jun 10 12:33 innd -rwxr-xr-x 1 root root 780 mai 2 00:21 kerneld -rwxr-xr-x 1 root root 903 mai 7 16:39 keytable -rwxr-xr-x 1 root root 447 jun 2 19:59 killall -rwxr-xr-x 1 root root 1015 mai 6 01:24 lpd -rwxr-xr-x 1 root root 4398 jun 2 19:59 network -rwxr-xr-x 1 root root 1299 jun 2 19:59 nfsfs -rwxr-xr-x 1 root root 1036 avr 6 00:15 pnserver -rwxr-xr-x 1 root root 1535 jun 2 19:59 random -rwxr-xr-x 1 root root 1138 mai 11 01:58 routed -rwxr-xr-x 1 root root 773 mai 6 05:18 rusersd -rwxr-xr-x 1 root root 780 mai 6 01:27 rwhod -rwxr-xr-x 1 root root 921 déc 31 1997 sendmail -rwxr-xr-x 1 root root 906 jun 2 19:59 single -rwxr-xr-x 1 root root 1372 mai 6 01:26 sound -rwxr-xr-x 1 root root 799 avr 30 07:53 syslogLes voici, nos fameux scripts ! Le contenu de ce répertoire varie en fonction des paquetages installés.
Examinons, par exemple, le script
inet:
$ less inet #! /bin/sh # # inet Start TCP/IP networking services. This script # sets the hostname, creates the routes and # starts the Internet Network Daemon & RPC portmapper.Le début de chaque script commence par indiquer les services qu'il assure : ici, celui des services TCP/IP, la configuration du nom de la machine, etc.
# See how we were called. case "$1" in start) echo -n "Starting INET services: " daemon inetd echo touch /var/lock/subsys/inet ;; stop) # bringing down NFS filesystems isn't inet's problem I don't know # why this script used to do that -- ewt echo -n "Stopping INET services: " killproc inetdpuis, le script regarde avec quel paramètre il a été appelé :
start, auquel cas il lance le programme assurant le service pour lequel il a été conçu (ici, avec la commandedaemon inetd), oustopauquel cas, il stoppe ce service (avec la commandekillproc inetd).
Certains scripts acceptent d'autres paramètres :
restartpar exemple, combine un appel avecstopet un appel avecstart.3.8 Conclusion sur l'
initSystem VVoilà, vous connaissez l'essentiel du mécanisme de démarrage/arrêt des services avec l'
initde System V. Si vous vous rendez compte qu'un service ne fonctionne pas :cron, par exemple, assurez-vous qu'un lienSvers le scriptcronexiste bien dans le répertoire correspondant au niveau d'exécution dans lequel vous travaillez. Si ce n'est pas le cas, créez-le. Pour son arrêt, ajoutez un lienKdansrc6.detrc0.dafin que le servicecronne soit stoppé qu'au moment de l'arrêt/redémarrage du système. Bien entendu, le scriptcrondoit exister dans/etc/rc.d/init.d... si ce n'est pas le cas, c'est probablement que vous n'avez pas installé le paquetage correspondant à ce service (vixie-cron-3.0.1-*, dans le cas de cron et d'un Red Hat).
Après tout ajout, pensez à relancer
init, ou faites-le à la main avec une commande comme./etc/rc.d/init.d/crond start. Vérifiez avec une commande commeps aux | egrep [c]rondque le service est bien lancé.
Passons maintenant à l'
initde la distribution Slackware.
Page suivante Page précédente Table des matières