Il existe aujourd'hui, dans le monde GNU/Linux, principalement deux boot loaders : lilo et grub. grub ayant l'avantage significatif de gérer des systèmes autres que Windows™ et Linux (*BSD, Solaris™, ..), nous allons aborder celui ci. .
grub est composé de deux programmes. Le premier (amorce grub) est installé dans le MBR. Le second est localisé dans le fichier /boot/grub/menu.lst dans le cas de distributions Debian, qui peut se situer sur n'importe quel disque, y compris un support amovible.
A l'inverse de lilo, grub n'a pas besoin d'être réinstallé dans le MBR à chaque modification de son fichier de configuration. Dans un système GNU/Linux, la commande grub-install est uniquement utilisée pour installer l'amorce de grub dans le MBR ou dans une partition. Les fichiers de configuration de grub doivent se trouver sur une partition utilisable, et dans le cas contraire, l'amorce exécute un interpréteur de commandes automatiquement.
Voici un exemple de fichier /etc/lilo.conf pour la distribution Debian :
timeout 60 default 1 fallback 0 title Debian root (hd1,0) kernel /boot/vmlinuz-2.6.20-15-generic ro single initrd /boot/initrd.img-2.6.20-15-generic title FreeBSD 6.2 root (hd0,0) chainloader +1
Enfin, grub dispose de nombreuses options de configuration que l'on peut mettre à jour dans le menu.lst.
Le système GNU/Linux[2] 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 1. Autres commandes
| niveau | sé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.
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.
Plusieurs distributions ayant fait le choix de développer de nouveaux modes de démarrage autour du processus init (upstart, initng, ..) nous ne nous étenderons pas sur le fihicer inita, qui a complètement disparu de plusieurs distributions. Néanmoins, pour des raisons de compatibilité, l'ensemble du processus de démarrage reste le même, et les paragraphes suivants sont toujours de mise
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 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.confexiste, 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/ifstatequi 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/interfaceset/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
set -e
# /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
if test -f /etc/default/ssh; then
. /etc/default/ssh
fi
. /lib/lsb/init-functions
check_for_no_start() {
# 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
log_end_msg 0
log_warning_msg "OpenBSD Secure Shell server not in use (/etc/ssh/sshd_not_to_be_run)"
exit 0
fi
}
check_privsep_dir() {
# Create the PrivSep empty dir if necessary
if [ ! -d /var/run/sshd ]; then
mkdir /var/run/sshd
chmod 0755 /var/run/sshd
fi
}
check_config() {
if [ ! -e /etc/ssh/sshd_not_to_be_run ]; then
/usr/sbin/sshd -t || exit 1
fi
}
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
case "$1" in
start)
log_begin_msg "Starting OpenBSD Secure Shell server..."
check_for_no_start
check_privsep_dir
start-stop-daemon --start --quiet --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS || log_end_msg 1
log_end_msg 0
;;
stop)
log_begin_msg "Stopping OpenBSD Secure Shell server..."
start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid || log_end_msg 1
log_end_msg 0
;;
reload|force-reload)
log_begin_msg "Reloading OpenBSD Secure Shell server's configuration"
check_for_no_start
check_config
start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd || log_end_msg 1
log_end_msg 0
;;
restart)
log_begin_msg "Restarting OpenBSD Secure Shell server..."
check_privsep_dir
check_config
start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sshd.pid
check_for_no_start
start-stop-daemon --start --quiet --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS || log_end_msg 1
log_end_msg 0
;;
*)
log_success_msg "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.