3. Démarrage et arrêt d'un système Unix

3.1. Organisation du disque d'un PC

Le disque dur d'un PC peut contenir différentes partitions, chacune pouvant accueillir un système d'exploitation. Cependant, à un instant donné seule l'une d'entre elles peut être active, elle correspond à celle chargée en mémoire au démarrage du PC.

Le premier secteur du disque contient une zone particulière appelée MBR [Master Boot Record] lequel décrit le schéma de partitionnement du disque. Cette zone est à l'origine du chargement du système quel qu'il soit.

Ce MBR d'une taille de 512 octets, est structuré ainsi :

  • les 446 premiers octets contiennent le loader (chargeur) qui doit charger le programme de chargement du système d'exploitation à lancer.

  • les 64 octets suivants décrivent les partitions en termes de taille, de localisation, de type et de statut. Cette structure est limitée à quatre entrées contraignant à quatre le nombre de partitions dites primaires ou principales. Cette limite peut être dépassée en faisant d'une des partitions primaires une partition dite étendue qui peut contenir des partitions logiques.

  • Enfin les 2 derniers octets contiennent le magic number, i.e. une valeur numérique qui permet à certains systèmes de vérifier la signature du secteur de boot.

3.2. Les étapes du processus de Boot

Au démarrage d'un PC, le programme de chargement situé dans le BIOS du système (stocké en ROM) est exécuté, son rôle est de charger le programme de chargement du MBR.

Il existe plusieurs programmes de chargement, citons lilo, le FreeBSD boot loader, grub ... Ces programmes peuvent démarrer tous les systèmes d'exploitation (OS) fonctionnant sur un PC. dans le cas le plus simple le chargeur lance l'OS de la partition marquée comme active. A l'extrême (plusieurs OS différents), le chargeur laisse à l'opérateur le soin de choisir le système qu'il veut lancer, puis charge le secteur de boot de l'OS choisi qui à son tour lance l'OS.

Le processus typique de bootstrapping (démarrage de l'OS) est décomposable en six étapes :

  1. Le chargement et l'initialisation du noyau.

  2. La détection et la configuration des périphériques.

  3. La création de processus système « spontanés ».

  4. L'intervention éventuelle de l'opérateur système (en mode manuel).

  5. L'exécution des scripts de démarrage.

  6. Les opérations en mode multi-utilisateurs.

3.2.1. Chargement et initialisation du noyau

Le noyau est un fichier stocké sur disque et l'une des première tâches du processus de démarrage est de le charger en mémoire.

GNU/Linux procède en deux temps :

  • Dans la première étape, la ROM charge en mémoire centrale (RAM) un petit programme localisé sur disque.

  • Dans la seconde, ce petit programme se charge de trouver et charger le noyau.

Le noyau détermine la quantité de RAM disponible, notamment pour ses structures internes dont certaines ont une taille statiquement fixée. Une certaine portion de cette mémoire est alors exclusivement réservée au noyau et ce dernier affiche sur la console le total de la mémoire trouvée et le total disponible pour les processus utilisateurs.

3.2.2. Détection et configuration des périphériques

Du point de vue conceptuel le noyau est une couche qui s'interface avec le matériel. La détection et la configuration des périphériques (matériels) disponibles est donc une tâche importante. Configurer son noyau c'est définir la configuration matérielle dans laquelle il s'exécutera.

Le noyau tente donc de localiser cette configuration attendue et recherche des informations supplémentaires en interrogeant directement les périphériques. Il imprime sur la console (et conserve) des informations quant à ces investigations.

A noter qu'il est très souvent possible d'activer dynamiquement un nouveau périphérique non prévu dans la configuration originale.

3.2.3. Processus systèmes

A ce stade le noyau va créer un certain nombre de processus qualifiés de spontanés, dans la mesure où il ne résulte pas du mécanisme standard de fork.

Le nombre et la nature de ces processus varient d'un système à l'autre. Avec GNU/Linux, il n'y a pas de processus visible de pid 0, le premier processus de pid 1 (i.e. INIT père de tous les processus utilisateurs subséquents) est accompagné d'un certain nombre de processus spontanés gérant le noyau (kflushd, ...), la mémoire (kswapd, ... ), les E/S (kiod, ...), la journalisation (kjournald pour ext3). Sous BSD 4.4 (le père des flavors xBSD, tous les processus sont les héritiers d'un processus unique crée au démarrage du système. Ce processus ancêtre génère trois processus spontanés [2] qui existe toujours tant que le système est démarré :

  • Le processus noyau swapper de pid 0 responsable du transfert entre la mémoire principale (RAM) et la mémoire secondaire (SWAP) des processus quand l'espace en mémoire principale est saturé.

  • Le processus noyau pagedaemon de pid 2 responsable de l'écriture de parties de l'espace d'adresse (pages) d'un processus vers la mémoire secondaire dans le contexte de gestion de la mémoire virtuelle.

  • Le processus utilisateur init de pid 1, premier processus à s'exécuter dans l'espace utilisateur (i.e. hors noyau) et ancêtre de tous les autres processus utilisateurs.

Lorsque ces processus « spontanés » ont été créés, l'étape de bootstrapping est terminée, néanmoins à ce stade la plupart des démons (processus systèmes) ne sont pas encore lancés, impossible par exemple de se connecter. La suite des opérations est prise en charge par le processus init.

3.2.4. Intervention de l'opérateur système (en mode manuel)

Si le système boote en mode single user, suite à l'activation d'un paramètre au démarrage, le noyau en avertit le processus init. Selon les systèmes, init peut éventuellement activer un sous-processus chargé de demander le mot de passe du super-utilisateur, puis si l'identification est réussie, init crée un shell de connexion.

Selon les systèmes (notamment Debian GNU/Linux, FreeBSD) seule la partition racine est montée en lecture seule. On exécute d'abord manuellement un fsck sur toutes les partitions, puis on remonte en écriture la partition racine, avant de remonter toutes les partitions restantes. Ensuite on exécute éventuellement les tâches qui ont requis ce mode.

Lorsque le travail est terminé, on met fin à ce mode pour soit passer directement en mode multi-utilisateur (séquence <CTRL>-D, sous FreeBSD) soit redémarrer/arrêter le système (commande shutdown).

3.2.5. Scripts de démarrage

Il s'agit de scripts shell choisis et exécutés par le processus init. Nous étudions cela dans une partie ultérieure (c.f. section Section 3.4.4, « Scripts de démarrage Debian »).

3.2.6. Opérations en mode multi-utilisateur

Après l'exécution des scripts de démarrage le système est quasi-fonctionnel, il ne manque que la possibilité de se logger. Chaque terminal (y compris la console) qui permet de se logger est contrôlé par un processus getty lancé par le processus init, ce dernier étant aussi responsable du lancement du gestionnaire de connexion en mode graphique (xdm ou wdm ou gdm...).

A l'issue de cette phase le système est complètement opérationnel et le processus init continue de jouer un rôle important (rappelons par exemple qu'il hérite des processus orphelins, qu'il gère le processus d'arrêt, reboot et passage en mode mono-utilisateur, ...).

3.3. Les étapes des scripts de démarrage

L'exécution des scripts de démarrage System V ou BSD permet d'exécuter les tâches suivantes :

  • l'attribution d'un nom de machine.

  • la définition du time zone.

  • la vérification de l'intégrité du système de fichiers (fsck) en mode automatique seulement.

  • le montage du système de fichiers

  • l'activation de(s) zone(s) de swap.

  • le nettoyage du système de fichiers (suppression des fichiers du répertoire temporaire), la vérification des quotas disque ...

  • la configuration des interfaces réseaux.

  • le lancement des démons (programmes serveurs) locaux

  • le lancement des démons réseau et le montage éventuels des partitions NFS.

  • le lancement des processus getty permettant aux utilisateurs de se connecter au système.

3.4. Démarrage et arrêt d'un système GNU/Linux

3.4.1. Démarrage avec lilo

Il existe aujourd'hui, dans le monde GNU/Linux, principalement deux boot loaders : lilo et grub. Nous étudions dans la suite le premier qui est souvent le boot loader par défaut. Nous proposons en exercice l'étude de grub.

Le programme lilo est composé de deux programmes. Le premier (amorce lilo) peut être installé soit dans le MBR soit sur le secteur de boot de la partition Linux. Le second est localisé dans le fichier /boot/boot.b

La commande /sbin/lilo permet de l'installer en exécutant les instructions contenues dans le fichier de configuration /etc/lilo.conf. Chaque fois que le processus de boot doit être changé (par exemple, suite à la recompilation d'un nouveau noyau), il faut modifier la configuration de lilo (i.e. le fichier /etc/lilo.conf) et ré-exécuter la commande /sbin/lilo pour la prise en compte.

Voici un exemple de fichier /etc/lilo.conf pour la distribution Debian :


# /etc/lilo.conf - See: `lilo(8)' and `lilo.conf(5)',                           
# ---------------       `install-mbr(8)', `/usr/share/doc/lilo/',
#                       and `/usr/share/doc/mbr/'.

# +---------------------------------------------------------------+
# |                        !! Reminder !!                         |
# | Don't forget to run `lilo' after you make changes to this     |
# | conffile, `/boot/bootmess.txt', or install a new kernel.  The |
# | computer will most likely fail to boot if a kernel-image      |
# | post-install script or you don't remember to run `lilo'.      |
# |                                                               |
# +---------------------------------------------------------------+

# Support LBA for large hard disks.
#
lba32

# Overrides the default mapping between harddisk names and the BIOS' harddisk 
# order. Use with caution.
#disk=/dev/hde
#    bios=0x81

# Specifies the boot device.  This is where Lilo installs its boot block.  It 
# can be either a partition, or the raw device, in which case it installs in 
# the MBR, and will overwrite the current MBR.
#

boot=/dev/hda 1


# Specifies the device that should be mounted as root. (`/')
#
root=/dev/hda3 

# Enable map compaction:
# Tries to merge read requests for adjacent sectors into a single read request.
# This drastically reduces load time and keeps the map smaller.  Using `compact' 
# is especially recommended when booting from a floppy disk.  It is disabled 
# here by default because it doesn't always work.
#
# compact

# Installs the specified file as the new boot sector. You have the choice 
# beween: bmp, compat, menu and text. Look in /boot/ and in lilo.conf(5) 
# manpage for details
#
install=/boot/boot-menu.b

# Specifies the location of the map file
#
map=/boot/map

# You can set a password here, and uncomment the `restricted' lines in the image
# definitions below to make it so that a password must be typed to boot anything 
# but a default configuration. If a command line is given, other than one speci-
# fied by an `append' statement in `lilo.conf', the password will be required, 
# but a standard default boot will not require one.
#
# This will, for instance, prevent anyone with access to the console from 
# booting with something like `Linux init=/bin/sh', and thus becoming `root' 
# without proper authorization.
#
# Note that if you really need this type of security, you will likely also want
# to use `install-mbr' to reconfigure the MBR program, as well as set up your
# BIOS to disallow booting from removable disk or CD-ROM, then put a password 
# on getting into the BIOS configuration as well.  Please RTFM `install-mbr(8)'.
#
# password=tatercounter2000

# Specifies the number of deciseconds (0.1 seconds) LILO should  wait before
#  booting the first image.
#
delay=20 

# You can put a customized boot message up if you like.  If you use `prompt', 
# and this computer may need to reboot unattended, you must specify a `timeout', 
# or it will sit there forever waiting for a keypress.  `single-key' goes with 
# the `alias' lines in the `image' configurations below.  eg: You can press `1' 
# to boot `Linux', `2' to boot `LinuxOLD', if you uncomment the `alias'.
#
# message=/boot/bootmess.txt
#	prompt
#	single-key
#	delay=100
#	timeout=100

# Specifies the VGA text mode at boot time. (normal, extended, ask, 
# <mode>)
#
vga=normal

# Kernel command line options that apply to all installed images go here.  See:
# The `boot-prompt-HOWO' and `kernel-parameters.txt' in the Linux kernel 
# `Documentation' directory.
#
# append=""

# Boot up Linux by default.
#
default=Linux

image=/vmlinuz  2

	label=Linux
	read-only
#	restricted
#	alias=1
	initrd=/initrd.img

image=/vmlinuz.ORIG
	label=LinuxORIG
	read-only
	optional
#	restricted
#	alias=2
	initrd=/initrd.img


# If you have another OS on this machine to boot, you can uncomment the
# following lines, changing the device name on the `other' line to
# where your other OS' partition is.
#

other=/dev/hda2    3

	label=OpenBSD
	restricted
	alias=3


1

Indique si le chargeur lilo est situé dans le MBR ou sur le secteur de boot de la partition Linux.

Ici dans le MBR.

2

Identifie les différentes images de noyaux Linux que peut charger lilo.

3

Spécifie le/les image(s) (secteurs de boot) du/des autres OS à charger.

L'installation du fichier de configuration précédent (/etc/lilo.conf), par la commande /sbin/lilo conduit à la sortie suivante :


# /sbin/lilo                                                                    
Added Linux*                                                                    
Added LinuxORIG
Added openBSD

Enfin, notons qu'au démarrage, le chargeur lilo attend 2 secondes, avant de charger le noyau /vmlinuz. On peut modifier ce déroulement au moment de l'affichage du prompt LILO: en appuyant sur la touche <TAB > qui permet de lister les options de boot possible.

3.4.2. Niveaux ou Runlevel

Le système GNU/Linux[3] a l'image de la famille Unix System V propose différents niveaux de fonctionnement (ou run levels). A un moment donné, un seul niveau peut être actif.

La commande init (associé au processus init) avec pour argument le niveau de fonctionnement, active l'ensemble des processus relatif à ce niveau.

Une même commande peut être associée à différents niveaux. Un niveau de son côté peut être une spécialisation du niveau précédent, i.e. il ajoute des services aux services déjà existant (par exemple le niveau 5 est une spécialisation du niveau 3). Un niveau peut aussi être complètement orthogonal au niveau qui le précède, ce qui se traduira par un mode de fonctionnement radicalement différent.

Unix System V défini traditionnellement huit niveaux de fonctionnement :

Tableau 6. Autres commandes

niveausémantique associée
0

hors-service. C'est le niveau utilisé pour arrêter la machine.

La machine peut être débranchée sans problème.

1

maintenance système, en mode console pour l'opérateur root uniquement.

s ou S

mode mono-utilisateur

2

mode multi-utilisateur. Système de fichiers montés, démons lancés (y compris réseau)

sauf RFS [Remote File System], exemple NFS [Network File System].

3

mode multi-utilisateur. Système de fichiers montés, démons lancés (y compris réseau)

plus RFS [Remote File System], exemple NFS ou CodaFS ...

Ce niveau est une spécialisation du niveau 2.

4

niveau définissable par l'administrateur.

5

Etat micro-code, utilisé à des fins de maintenance et de diagnostics.

6

Etat reboot, i.e. mise hors service suivie du redémarrage.


La plupart des distributions GNU/Linux orientée System V ont adopté ces niveaux de fonctionnement. Certaines rajoutent même les niveaux 7,8,9 définisables par l'utilisateur. Le niveau 5 est traditionnellement associé au mode de connexion graphique avec le gestionnaire (par défaut) xdm. Enfin, les niveaux 1 et S (ou s) sont généralement indifférenciés, ce qui réduit à sept le nombre de niveaux. La distribution Debian n'utilise pas pour sa part les run levels 3,4 et 5.

3.4.3. Le fichier /etc/inittab

Le processus init contrôle généralement le démarrage en mode multi-utilisateur. Rappelons qu'au démarrage la tâche du chargeur [loader] est de charger le noyau en mémoire prinicpale. Le noyau crée, entre autre, le processus init qui va analyser le fichier de configuration /etc/initab pour déterminer les actions à accomplir.

Le fichier /etc/initab est un fichier de type texte structuré en parties séparées par de commentaires. La syntaxe d'une ligne typique (hors commentaire) est la suivante :

id:runlevels:action:process:

où :

  • id : est un identificateur permettant d'identifier la ligne sans ambiguïté.

  • runlevels : Liste le ou les niveaux dans le(s)quel(s) la commande doit être exécutée. Un argument vide signifie tous les niveaux sauf s (i.e. 0123456).

  • action : permet de préciser le contexte d'exécution de la commande à exécuter. Les valeurs possibles sont les suivantes :

    • initdefault : spécifie le niveau de fonctionnement par défaut, généralement 2 ou 3. Si cette ligne n'existe pas, le système demande le niveau de démarrage souhaité sur la console.

    • boot : la commande est exécutée uniquement au démarrage du système, de plus init n'attend pas sa terminaison pour poursuivre son travail en analysant et exécutant les lignes suivantes du fichier.

    • bootwait : la commande est exécutée uniquement au démarrage du système, mais init attend sa terminaison avant de poursuivre son travail.

    • once : exécute la commande si elle n'est pas déjà lancée, sans attendre sa terminaison, pour passer à la suite.

    • wait : comme précédemment mais avec attente de la terminaison.

    • respawn : exécute la commande une première fois lorsqu'init analyse son fichier de configuration et reéxecute la commande si elle se termine.

    • sysinit : exécuté une seule fois au démarrage à froid du système, sans tenir compte du niveau (i.e. tous niveaux). Réservées aux tâches fondamentales nécessaires au bon fonctionnement du système.

    • off : Si le processus associé à ce niveau s'exécute, le terminer. Permet aussi de désactiver les terminaux.

    • power{wait,failnow,okwait} : ...

  • process : désigne la commande à exécuter.

Voici le contenu du fichier /etc/initab d'une Debian woody :

# /etc/inittab: init(8) configuration.                                 
# $Id: inittab,v 1.1.1.1 2005/05/14 06:32:58 pascal Exp $

# The default runlevel.
id:2:initdefault:  1

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS 2

# What to do in single-user mode.
~~:S:wait:/sbin/sulogin 3

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0 
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2 4
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin

# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now 5

# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start 6
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  <id>:<runlevels>:<action>:<process>
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty's go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty 38400 tty1 7
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6

# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100

# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3

1

Niveau de fonctionnement par défaut : 2

2

Exécution de la commande à tous les niveaux : 0123456, sauf S.

3

Demmander le mot de passe de root avant d'entrer dans le mode single-user.

4

Exécute le script (/etc/init.d/rc) de démarrage avec le niveau de fonctionnement passé en paramètre, ici 2 (c.f. ligne initdefault).

5

Commande exécutée lorsque la séquence de touches <CTRL>-<ALT>-<DEL> est pressée dans les niveaux 12345.

6

Action à entreprendre en cas de panne électrique (indiquée par un onduleur)...

7

Activation des terminaux et réactivation si déconnexion.

3.4.4. Scripts de démarrage Debian

Au démarrage « normal » de Debian, le premier script exécuté par le processus init est etc/init.d/rcS (c.f. contenu du fichier /etc/initab en section Section 3.4.3, « Le fichier /etc/inittab »), lequel exécute à son tour les scripts du répertoire /etc/init.d. Ils contiennent l'ensemble des commandes indispensables à l'initialisation et au contrôle du système. Globalement, ils permettent :

  • S05initrd-tools.sh : démonte et libère le RAM disk initialisé par le boot loader lors du démarrage et utilisé par le noyau pour son chargement en deux temps.

  • S05keymap.sh : chargement des préférences clavier (azerty, français par exemple).

  • S10checkroot.sh : activation du swap, vérification et montage de la partition racine (/).

  • S18hwclockfirst.sh : positionnement de l'horloge système en fonction de l'horloge matérielle en tenant compte du paramètre UTC (/etc/default/rcS).

  • S20modutils : vérification des dépendances entres modules et chargement.

  • S30checkfs.sh : vérification du reste du système de fichiers local.

  • S30etc-setserial : configuration des périphériques séries si le fichier de configuration manuelle /etc/serial.conf existe, sinon la configuration automatique intervient plus tard, voir le script S46setserial.

  • S30procps.sh :

  • S35devpts.sh : montage du système devpts, si devfs existe et est monté.

  • S35mountall.sh : montage du reste du système de fichiers local.

  • S35quota : vérification des quotas disques.

  • S39dns-clean : nettoyage du fichier /etc/resolv.conf (éventuellemnt modifié lors des connexions ppp).

  • S39ifupdown : remise à zéro du fichier /etc/network/ifstate qui liste les interfaces réseaux actives.

  • S40hostname.sh : attribution du nom machine, par lecture du fichier /etc/hostname.

  • S40iptables : restauration des règles du firewall, si elles existent et ont été préalablement sauvegardées.

  • S40networking : activation des interfaces réseaux et positionnement d'options. Ce script fait appel à /sbin/ifup (et /sbin/ifdown) et utilise les informations de configuration stockées dans /etc/network/interfaces et /etc/network/options.

  • S41portmap : démarrage du démon portmap, lequel active les services RPC [Remote Procedure Call] nécessaire par exemple au système de fichiers NFS [Network File System].

  • S45mountnfs.sh : montage des partitions NFS.

  • S46setserial : activation/restauration des périphériques séries (mode automatique).

  • S48console-screen.sh : chargement des paramètres pour les consoles.

  • S50hwclock.sh ajustement de l'horloge CMOS relativement au paramètre UTC (/etc/default/rcS).(

  • S55bootmisc.sh : tâches diverses à réaliser au démarrage (nettoyage des fichiers temporaires, effacement des verrous non libérés ...).

  • S55urandom : initialisation du générateur de nombres aléatoires.

  • S70nviboot : recouvrement des sessions éditeur vi.

  • S75sudo : activation du programme sudo

Le processus init poursuit son exécution en lançant le script spécifique (/etc/rc.d/rc 2) du niveau de fonctionnement souhaité. Dans le cas d'une Debian c'est le niveau 2 (initdefault). Ce script lance à son tour les scripts contenus dans le répertoire /etc/rc2.d. Ces scripts sont en fait des liens symboliques sur d'autres scripts (scripts « maîtres ») placés dans le répertoire /etc/init.d.

Exemple 1. Un contenu du répertoire /etc/rc2.d.


S10sysklogd -> ../init.d/sysklogd
S11klogd -> ../init.d/klogd
S14ppp -> ../init.d/ppp
S18quotarpc -> ../init.d/quotarpc
S19amavis-postfix -> ../init.d/amavis-postfix
S20acct -> ../init.d/acct
S20bastille-firewall -> ../init.d/bastille-firewall                             
S20binfmt-support -> ../init.d/binfmt-support
S20inetd -> ../init.d/inetd
S20lpd -> ../init.d/lpd
S20makedev -> ../init.d/makedev
S20mysql -> ../init.d/mysql
20nfs-kernel-server -> ../init.d/nfs-kernel-server
S20postfix -> ../init.d/postfix
20postgresql -> ../init.d/postgresql
S20samba -> ../init.d/samba
S20ssh -> ../init.d/ssh
S20xfs -> ../init.d/xfs
S20xfstt -> ../init.d/xfstt
S21nfs-common -> ../init.d/nfs-common
S89atd -> ../init.d/atd
S89cron -> ../init.d/cron
S91apache -> ../init.d/apache
S91apache-ssl -> ../init.d/apache-ssl
S99fetchmail -> ../init.d/fetchmail
S99rmnologin -> ../init.d/rmnologin
S99wdm -> ../init.d/wdm
S99xdm -> ../init.d/xdm


Tous les scripts commencent soit par la lettre K (c.f. niveau de fonctionnement 6), soit par la lettre S suivi d'un numéro à deux chiffres puis d'un nom significatif. Cette convention permet d'ordonner les scripts dans l'ordre lexicographique ; ordre utilisé pour l'exécution.

Entrer dans un niveau de fonctionnement implique d'abord l'exécution des scripts commençant par la lettre K (appel des scripts « maîtres » avec l'argument stop) dont le rôle est d'arrêter les démons (services) puis l'exécution des scripts commençant par la lettre S (argument start), pour (re)démarrer les démons.

Les scripts « maîtres » sont en mesure de traiter l'argument qui leur est passé en paramètre, ce dernier prenant les valeurs classiques : start, stop, reload, restart, force-reload...

Exemple 2. Un exemple de script


#! /bin/sh

# /etc/init.d/ssh: start and stop the OpenBSD "secure shell(tm)" daemon

test -x /usr/sbin/sshd || exit 0
( /usr/sbin/sshd -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0

# forget it if we're trying to start, and /etc/ssh/sshd_not_to_be_run exists
if [ -e /etc/ssh/sshd_not_to_be_run ]; then 
    echo "OpenBSD Secure Shell server not in use (/etc/ssh/sshd_not_to_be_run)" 
    exit 0
fi

check_config() {
	/usr/sbin/sshd -t || exit 1
}

# Configurable options:

case "$1" in
  start)
	test -f /etc/ssh/sshd_not_to_be_run && exit 0
#Create the PrivSep empty dir if necessary
	if [ ! -d /var/run/sshd ]; then
	    mkdir /var/run/sshd; chmod 0755 /var/run/sshd
	fi
        echo -n "Starting OpenBSD Secure Shell server: sshd"
	start-stop-daemon --start --quiet --pidfile /var/run/sshd.pid \ 
                          --exec /usr/sbin/sshd
        echo "."
	;;
  stop)
        echo -n "Stopping OpenBSD Secure Shell server: sshd"
	start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid
        echo "."
	;;

  reload|force-reload)
  	test -f /etc/ssh/sshd_not_to_be_run && exit 0
	check_config
        echo -n "Reloading OpenBSD Secure Shell server's configuration"
	start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile \
                          /var/run/sshd.pid --exec /usr/sbin/sshd
	echo "."
	;;

  restart)
  	test -f /etc/ssh/sshd_not_to_be_run && exit 0
	check_config
        echo -n "Restarting OpenBSD Secure Shell server: sshd"
	start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid
	sleep 2
	start-stop-daemon --start --quiet --pidfile /var/run/sshd.pid \
                          --exec /usr/sbin/sshd
	echo "."
	;;

  *)
	echo "Usage: /etc/init.d/ssh {start|stop|reload|force-reload|restart}"
	exit 1
esac

exit 0


Exemple 3. Ajouter un script sous Debian avec update-rc

L'administrateur doit ajouter un nouveau script baptisé test dans le répertoire /etc/init.d. Il s'agit d'un script shell qui sait répondre aux mots-clés start et stop. Ce script doit être démarré dans le run level 2 et arrêté dans les run levels 0, 1 et 6. Sous Debian, l'administrateur dispose du script update-rc.d pour installer tous les liens symboliques nécessaires (ici il attribue le numéro d'ordre 92) :


tux:~# update-rc.d test start 92 2 . stop 0 1 6 .
tux:~# ls -l /etc/rc2.d/S??test
lrwxrwxrwx  1 root  root  11 Mar 24 10:17 S92test -> ../init.d/test             
tux:~# ls -l /etc/rc0.d/K??test
lrwxrwxrwx  1 root  root  11 Mar 24 10:17 K92test -> ../init.d/test


Suite de l'exécution /etc/inittab : activation des terminaux.

3.5. Démarrage et arrêt d'un système BSD

Un système Unix possède fondamentalement trois niveaux de fonctionnement :

  • hors service, i.e. non allumé.

  • mode mono-utilisateur.

  • mode multi-utilisateur (mode de fonctionnement normal).

Nous avons vu au paragraphe Section 3.4.2, « Niveaux ou Runlevel » ajoute d'autres niveaux à ces trois niveaux fondamentaux, ce qui n'est pas le cas de la famille BSD.

--- F I X M E : FreeBSD branches 4.X et 5.Y ( Y < 3)

La distribution FreeBSD exécute le script /etc/rc au démarrage. Son but est de vérifier et monter les système de fichiers, d'activer les interfaces réseaux, de configurer les périphériques ... Plutôt que d'utiliser un long script monolithique, les développeurs de cette distribution ont opté pour de petits scripts réalisant chacun une tâche bien définie. Ils sont appelés depuis le script « maître » /etc/rc. En voici la liste :

  • /etc/rc.atm : configuration du réseau ATM.

  • /etc/rc.diskless1, /etc/rc.diskless2 : utlisé pour lancer un système FreeBSD sans disque.

  • /etc/rc.firewall : activation du firewall (ipfw) pour la famille de protocole IPv4.

  • /etc/rc.firewall6 : activation du firewall (ipfw) pour la famille de protocole IPv6.

  • /etc/rc.i386 : script d'initialisation pour les systèmes basés sur l'architecture i386.

  • /etc/rc.isdn : configuration et activation de(s) l'interface(s) ISDN.

  • /etc/rc.network : activation du réseau en IPv4.

  • /etc/rc.network6 : activation du réseau en IPv6.

  • /etc/rc.pccard : configuration de(s) l'interface(s) PCMCIA.

  • /etc/rc.resume : gestion de l'évènement APM resume.

  • /etc/rc.sendmail : démarrage du démon sendmail.

  • /etc/rc.serial : paramétrage des périphériques sériels.

  • /etc/rc.shutdown : pour l'arrêt des démons lors d'un arrêt ou lors de la transition mode multi-utilisateur vers le mode mon-utilisateur.

  • /etc/rc.suspend : gestion de l'évènement APM suspend.

  • /etc/rc.syscons : configuration des terminaux : type de clavier, screensaver ...

  • /etc/rc.sysctl : positionnement des valeurs sysctl, par lecture du fichier /etc/sysctl.conf

La configuration du script « maître » intervient dans deux fichiers /etc/default/rc.conf et /etc/rc.conf. Le premier contient de très nombreux paramètres réglables [tunable knobs en terminologie FreeBSD] avec leurs valeurs par défauts. Le second contient un sous-ensemble de ces paramètres avec les valeurs déterminées par l'administrateur. La personnalisation des paramètres intervient toujours dans ce second fichier, puisque ses définitions ont pour but de redéfinir les valeurs par défaut. Une lecture attentive du man section 5 de rc.conf permet de tout savoir sur les paramètres à régler.

Exemple 4. Un exemple de fichier de configuration /etc/rc.conf


# -- sysinstall generated deltas -- # Fri Jan  4 11:31:55 2000
#
# godel
#
# Created: Fri Jan  4 11:31:55 2000
# Enable network daemons for user convenience.
# Please make all changes to this file, not to /etc/defaults/rc.conf.
# This file now contains just the overrides from /etc/defaults/rc.conf.

accounting_enable="YES"
defaultrouter="192.168.200.1"

font8x8="iso15-8x8"
font8x14="iso15-8x14"
font8x16="iso15-8x16"

allscreens_flags="132x43"

hostname="Godel.corto.home"
ifconfig_xl0="inet 192.168.200.2  netmask 255.255.255.0"
#ifconfig_xl0_alias0="inet 10.1.1.2  netmask 255.255.255.0"

inetd_enable="NO"
inetd_flags="-l -W -w"  

ipv6_enable="NO"

kern_securelevel="2"
kern_securelevel_enable="NO"

keymap="fr.iso.acc"

linux_enable="YES"
lpd_enable="NO"

moused_enable="NO"
moused_flags="-z 4"

#nfs_reserved_port_only="YES"
#nfs_server_enable="YES"
#portmap_enable="YES"
#mountd_flags="-r"

saver="logo"

# disable sendmail --> activate postfix (/etc/mail/mail.conf)                   
sendmail_enable="YES"
sendmail_flags="-bd"
sendmail_outbound_enable="NO"
sendmail_submit_enable="NO"
sendmail_msp_queue_enable="NO"

sshd_enable="YES"
sshd_flags="-f /etc/ssh/sshd_config -4"
sshd_program="/usr/sbin/sshd"

usbd_enable="NO"
syslogd_flags="-ss"

## ajoute le 29.05.2000
update_motd="NO"

ipfilter_enable="YES"
ipfilter_program="/sbin/ipf"
ipfilter_rules="/etc/ipf.conf"
ipfilter_flags="-E -v"

ipnat_enable="NO"

ipmon_enable="YES"
ipmon_flags="-Dsnv"

# (break RFC compliance !)
tcp_drop_synfin="YES"

icmp_drop_redirect="YES"
icmp_log_redirect="YES"

start_vinum="YES"


Tableau 7. Quelques paramètres de personnalisation

paramètresémantique associée
hostname="Godel.corto.home"

Nom de la machine, au sens du DNS.

defaultrouter="192.168.200.1"

adresse réseau de la passerelle.

ifconfig_xl0="inet 192.168.200.2 netmask 255.255.255.0"

Configuration de l'interface réseau, ici une carte ethernet 3Com™.

ifconfig_xl0_alias0="inet 10.10.129.145 netmask 255.255.255.0"

Permet d'associer une nouvelle adresse IP à la même interface.

inetd_enable="NO"

Désactive le « démon » inetd.

sshd_enable="YES"

Active le « démon » sshd.

keymap="fr.iso.acc"

Clavier de type azerty français.


--- T O D O : démarrage FreeBSD branche 6.X - The new way

L'initialisation via INIT n'est plus basé sur le script « monolithique », mais sur un mécanisme hybride BSD/System V, importé du flavor NetBSD qui, sans être révolutionnaire, permet davantage de souplesse.

3.6. Arrêt du système [shutdown] et redémarrage [reboot]

Les changements dans les tampons mémoires [buffers] ne sont pas immédiatement répercutés sur disque, on parle d'écritures asynchrones. Cela permet d'améliorer notablement les performances des opérations d'E/S. Mais le système est susceptible de perdre des données en cas d'arrêt imprévu (c'est moins le cas aujourd'hui pour les systèmes de fichiers journalisés).

Savoir arrêter ou rebooter son système correctement permet d'éviter bien des problèmes. Ils existent plusieurs méthodes :

  • Utiliser la commande /sbin/shutdown

  • Utiliser la commande /sbin/halt ou /sbin/reboot

  • Utiliser la commande (GNU/Linux) telinit ou init.

  • Utiliser la commande (GNU/Linux) /sbin/poweroff.

La commande /sbin/shutdown (GNU/Linux)

SYNOPSIS :
                                                                                

shutdown [-t sec] [-arkhncfF] [time] [warning-message]

C'est la manière la plus sûre pour :

  • arrêter proprement (-h) le système,

  • rebooter proprement (-r) le système,

  • passer en mode mono-utilisateur (option par défaut).

Cette commande prévient les processus en cours d'exécution en leur envoyant le signal de terminaison SIGTERM. Elle notifie au processus INIT le changement de runlevel :

  • 0 [init 0] : arrêt.

  • 1 [init 1] : mode mono-utilisateur, maintenance.

  • 6 [init 6] : reboot.

Arrêter le système immédiatement [runleval 0] : /sbin/shutdown -h now.

Arrêter dans 20 minutes [runlevel 0] :

# /sbin/shutdown -h +20 "Arret du systeme, pour maintenance"                    


Reboot à 12h30 (runlevel 6) :                                                   

# /sbin/shutdown -r 12:30                                                       

La commande /sbin/halt (GNU/Linux)

SYNOPSIS :
                                                                                

halt [-n] [-w] [-d] [-f] [-i]

Exécute les tâches essentielles pour l'arrêt du système (appelé par la commande shutdown avec l'argument -h) :

  • termine les processus non essentiels.

  • exécute l'appel système call.

  • attend que toutes les écritures soient complètes.

  • arrête le noyau.

Arrêter le système immédiatement :

# /sbin/halt                                                                    

La commande /sbin/reboot (GNU/Linux)

SYNOPSIS :
                                                                                

reboot [-n] [-w] [-d] [-f] [-i]

Fonctionnement similaire à la commande halt, mais effectue un redémarrage [reboot].

« Rebooter » le système immédiatement :

# /sbin/reboot                                                                  

La commande /sbin/init (GNU/Linux)

La commande telinit est un lien symbolique sur init.

SYNOPSIS :
                                                                                

init [-a] [-s] [-b] [-z xxx] [0123456Ss]

Passer en mode maintenance (mono-utilisateur)

# /sbin/init 1                                                                  

La commande /sbin/poweroff (GNU/Linux)

SYNOPSIS :
                                                                                

poweroff [-n] [-w] [-d] [-f] [-i] [-h]

Fonctionnement identique à la commande halt, mais envoit une requête pour couper explicitement l'alimentation électrique sur les systèmes possèdant un gestionnaire d'alimentation.

3.7. Exercices

--- T O D O :



[2] Les flavors BSD héritière de la branche 4.4 génère d'autres processus [en fait des kernel threads] ] (wmdaemon, bufdaemon, wnlru ... sous FreeBSD, par exemple).

[3] A la notable exception de la distribution Linux Slackware, orienté BSD.