syslog
inetd
cron
et atd
anacron
init
. Il est fréquent que cette « partition racine » et cet init
soient en réalité sur un système de fichiers virtuel qui n'existe qu'en mémoire vive (d'où son nom initramfs, anciennement appelé initrd pour initialization RAM disk). Ce système de fichiers est chargé en mémoire par le chargeur d'amorçage, souvent à partir d'un fichier sur un disque dur ou sur le réseau. Il contient le strict minimum qui peut être requis par le noyau pour charger le « vrai » système de fichiers racine : il peut s'agir de modules de pilotes pour les disques durs ou d'autres périphériques sans lesquels le système ne peut pas démarrer, ou, plus fréquemment, des modules et des scripts d'initialisation permettant d'assembler des grappes RAID, d'ouvrir des partitions chiffrées, d'activer des volumes LVM… Une fois que la partition racine est montée, l'initramfs passe la main au vrai init
et on revient sur le processus de démarrage standard.
systemd
exécute plusieurs processus qui ont la responsabilité de mettre en place le système : clavier, pilotes, systèmes de fichiers, réseau et services. Il effectue cela en conservant une vue globale du système et des exigences de chaque composant. Chaque composant est décrit par un (ou plusieurs) « fichier unité » (unit file) ; la syntaxe générale est dérivée de celle des « fichiers *.ini », avec des paires clé = valeur
regroupées entre des en-têtes [section]
. Ces fichiers sont placés dans /lib/systemd/system/
et dans /etc/systemd/system/
; ils en existent plusieurs sortes (chacune avec sa spécialité) mais dans cette section on ne traitera que des services et des targets (« cibles »).
systemd
s'occupe de toutes les tâches répétitives (démarrer et arrêter le processus, vérifier son état, enregistrer des logs, abandonner des privilèges, etc.), et le fichier service n'a plus qu'à préciser les particularités du processus. Voici par exemple celui pour SSH :
[Unit] Description=OpenBSD Secure Shell server After=network.target auditd.service ConditionPathExists= !/etc/ssh/sshd_not_to_be_run [Service] EnvironmentFile=-/etc/default/ssh ExecStart=/usr/sbin/sshd -D $SSHD_OPTS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure [Install] WantedBy=multi-user.target Alias=sshd.service
systemd
s'occupe d'afficher l'état d'avancement, garde une trace des processus, et les redémarre même lorsque c'est nécessaire.
local-fs.target
; lorsqu'elle est atteinte, le reste du système peut considérer que tous les systèmes de fichiers locaux sont montés et accessibles. Parmi les autres cibles existantes, citons network-online.target
(« réseau en ligne ») et sound.target
(« son »). Les dépendances d'une cible peuvent être listées soit dans le fichier target lui-même (sur la ligne Requires=
), soit en créant un lien symbolique vers un fichier service dans le répertoire /lib/systemd/system/nom-de-la-cible.target.wants/
. Ainsi, /etc/systemd/system/printer.target.wants/
contient un lien vers /lib/systemd/system/cups.service
; systemd s'assurera donc que CUPS soit bien démarré pour atteindre la cible printer.target
.
systemctl
. Lorsqu'il est exécuté sans paramètres, il liste toutes les « unités » connues de systemd (à l'exception de celles qui ont été désactivées), ainsi que leur état. systemctl status
donne une meilleure vue des services, et des processus associés. En lui passant un nom de service (comme dans systemctl status ntp.service
), il renvoie encore plus de détails, ainsi que les dernières lignes de log en rapport avec le service (nous reviendrons là dessus plus loin).
systemctl start nom-de-service.service
. Inversement et sans surprise, arrêter un service se fait avec systemctl stop nom-de-service.service
; d'autres sous-commandes existent, comme reload
(« recharger ») et restart
(« redémarrer »).
systemctl enable nom-du-service.service
(ou disable
pour le désactiver). La sous-commande is-enabled
permet de vérifier l'état d'activation du service.
journald
. Il peut être employé en complément des outils de journalisation traditionnels comme syslogd
: il rajoute des fonctionnalités intéressantes comme l'association d'un message au service qui l'a généré, et la capacité de capturer les messages émis sur la sortie d'erreur des processus gérés. Les messages peuvent être consultés après coup, grâce à la commande journalctl
. Sans arguments, elle affiche simplement tous les messages enregistrés depuis le démarrage du système ; on ne l'emploie que rarement de cette manière. La plupart du temps, on lui communique un identifiant de service dont on veut voir les messages :
#
journalctl -u ssh.service
-- Logs begin at mar. 2015-03-31 10:08:49 CEST, end at mar. 2015-03-31 17:06:02 CEST. -- Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22. Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22. Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting. Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22. Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22. Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2 Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)
-f
, qui demande à journalctl
d'afficher les nouveaux messages au fur et à mesure de leur émission (de manière similaire à ce que réalise tail -f fichier
).
systemctl status
; si ce n'est pas le cas, et si les messages affichés par cette première commande ne suffisent pas à identifier le problème, il convient alors de consulter les messages que journald a collecté au sujet de ce service. Prenons le cas d'un serveur SSH qui ne fonctionne pas :
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; enabled) Active: failed (Result: start-limit) since mar. 2015-03-31 17:30:36 CEST; 1s ago Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS) Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255) Main PID: 1188 (code=exited, status=255) Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state. Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start. Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server. Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state. #
journalctl -u ssh.service
-- Logs begin at mar. 2015-03-31 17:29:27 CEST, end at mar. 2015-03-31 17:30:36 CEST. -- Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22. Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22. Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting. Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22. Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22. Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2 Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0) Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess". Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state. Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess". Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state. Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess". Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state. Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess". Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state. Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess". Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state. Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start. Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server. Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state. #
vi /etc/ssh/sshd_config
#
systemctl start ssh.service
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; enabled) Active: active (running) since mar. 2015-03-31 17:31:09 CEST; 2s ago Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS) Main PID: 1222 (sshd) CGroup: /system.slice/ssh.service └─1222 /usr/sbin/sshd -D #
/etc/inittab
. Le premier programme exécuté (correspondant à l'étape sysinit) est /etc/init.d/rcS
, script qui exécute tous les programmes du répertoire /etc/rcS.d/
.
/etc/modules
;
init
reprend la main et démarre les programmes associés au niveau d'exécution (runlevel) normal, soit par défaut le niveau 2. Il exécute /etc/init.d/rc 2
, script qui démarre tous les services donnés du répertoire /etc/rc2.d/
débutant par la lettre « S ». Le nombre (à deux chiffres) qui suit servait historiquement à classer les services pour les démarrer dans le bon ordre, mais de nos jours le système de démarrage par défaut utilise insserv
, un système de démarrage où l'ordonnancement se fait en fonction des dépendances entre scripts. Chaque script de démarrage déclare ainsi les contraintes qui s'appliquent à lui (par exemple, s'il doit démarrer avant ou après tel autre service) ; init
les lance alors dans un ordre qui satisfait les contraintes. La numérotation statique des scripts n'est donc plus prise en compte (mais ils doivent toujours s'appeler d'un nom composé d'un « S » suivi de deux caractères, suivis à leur tour du véritable nom du script utilisé pour les dépendances). D'une manière générale, les services de base (comme le service de collecte des journaux, rsyslog
, ou celui d'attribution des ports, portmap
) sont démarrés en premier, suivis par les services standards et l'interface graphique (gdm3
).
init
distingue plusieurs niveaux d'exécution car il peut basculer de l'un à l'autre par la commande telinit nouveau-niveau
. Dès son invocation, init
exécute à nouveau /etc/init.d/rc
avec le nouveau niveau d'exécution désiré, script qui démarre à son tour les services manquants et arrête ceux qui ne sont plus souhaités. Pour cela, il se réfère au contenu du répertoire /etc/rcX.d
(où X représente le nouveau niveau d'exécution). Les scripts débutant par « S » (comme Start) sont des services à démarrer, ceux débutant par « K » (comme Kill) sont des services à stopper. Le script évite de redémarrer tout service déjà actif dans le niveau d'exécution précédent.
/etc/rcX.d/
correspondants) pour les adapter à un besoin particulier.
Figure 9.2. Étapes du démarrage d'un ordinateur sous Linux avec le système d'initialisation System V
/etc/rcX.d
ne sont que des liens symboliques, créés à l'installation du paquet concerné par le programme update-rc.d
, et menant vers les scripts réels, stockés sous /etc/init.d/
. Pour adapter à sa guise les services à démarrer ou à stopper à chaque niveau d'exécution, l'administrateur exécutera à nouveau le programme update-rc.d
en lui fournissant les paramètres adéquats. La page de manuel update-rc.d(1) en détaille la syntaxe précise. Signalons au passage que supprimer tous les liens symboliques (avec le paramètre remove
) n'est pas la bonne méthode pour désactiver un service. Il faut simplement le configurer pour ne pas démarrer dans les niveaux d'exécution souhaités (tout en conservant les appels correspondants pour l'arrêter au cas où le service tournait dans le niveau d'exécution précédent). L'utilisation d'update-rc.d
étant quelque peu alambiquée, on pourra utiliser rcconf
(du paquet rcconf) pour se voir présenter une interface plus simple à manipuler.
init
démarre les programmes de contrôle des différentes consoles virtuelles (getty
). Ils affichent une invite, attendent un nom d'utilisateur, puis exécutent login utilisateur
pour démarrer une session.