Aller au contenu

Gérer les services

Objectif : manipuler les services et gérer le démarrage et l'arrêt d'un système Linux.

Au cours des précédents ateliers, nous avons eu l'occasion de parler des "services", ces logiciels qui tournent en tâche de fond pendant que l'utilisateur fait autre chose. C'est un peu comme un serveur (un vrai, en chair et en os) dans un café, discrètement à l'affût dans un coin, attendant que vous daigniez interrompre la lecture de votre journal pour commander un café et deux croissants.

Cet exemple est résolument utopique. Dans un café français qui se respecte, c'est le client qui est à l'affût du serveur.

Certains de ces services sont indispensables pour le fonctionnement cohérent du système et doivent être lancés au démarrage de la machine. D'autres sont facultatifs et dépendent de l'utilisation spécifique que vous faites de votre serveur. Le présent chapitre vous propose une introduction facile et pratique à la gestion des services sous Oracle Linux.

Qu'est-ce qu'un service ?

Pour avoir une idée de ce qu'est un service, nous n'avons qu'à en prendre un au hasard sur notre machine pour le regarder de près :

$ ps ax | grep -v grep | grep sshd
 1016 ?        Ss     0:00 /usr/sbin/sshd -D
 1267 ?        Ss     0:00 sshd: microlinux [priv]
 1271 ?        S      0:00 sshd: microlinux@pts/0

Le service OpenSSH (/usr/sbin/sshd) attend en permanence des connexions depuis des clients. Lorsqu'il reçoit une requête, il se charge d'établir une connexion sécurisée après une authentification.

Un service connaît principalement deux états :

  • marche ;

  • arrêt.

C'est un peu comme le moteur d'une voiture. Soit il est démarré, soit il ne tourne pas. Après, savoir si vous le laissez tourner au point mort ou si vous embrayez, c'est une autre histoire...

Arrêter et (re)démarrer un service

Dans une voiture, je coupe le contact pour arrêter le moteur. Je peux faire pareil pour un service, après avoir acquis les droits d'administrateur :

$ sudo systemctl stop sshd

Vous serez peut-être vaguement surpris de ne pas avoir été déconnecté. Essayez de lancer une deuxième session à distance :

[microlinux@alphamule:~] $ ssh linuxbox
ssh: connect to host linuxbox port 22: Connection refused

Pour relancer le service, je dois invoquer la commande suivante :

$ sudo systemctl start sshd

Le serveur est à nouveau accessible depuis une machine distante :

[microlinux@alphamule:~] $ ssh linuxbox
microlinux@linuxbox's password:

Dans certaines situations, il est nécessaire de redémarrer un service, par exemple après avoir apporté des modifications à sa configuration, pour que celles-ci soient prises en compte :

$ sudo systemctl restart sshd

Le "redémarrage" n'est pas véritablement une fonctionnalité à part. Pour le système, il s'agit simplement d'une commande stop suivie d'une commande start.

Interdire les connexions SSH de l'utilisateur root

Dans la configuration par défaut d'Oracle Linux 7, le serveur OpenSSH accepte les connexions distantes de l'utilisateur root. Pour renforcer la sécurité de leurs machines, certains administrateurs interdisent à root de se connecter directement.

Pour mettre en place cette politique, il faut éditer le fichier /etc/ssh/sshd_config. Repérez la directive PermitRootLogin, décommentez la ligne en supprimant le dièse # initial et passez la directive à no :

PermitRootLogin no

Redémarrez le service SSH pour prendre en compte les modifications :

$ sudo systemctl restart sshd

Recharger la configuration d'un service

Certains services – dont OpenSSH – sont capables de prendre en compte une nouvelle configuration sans pour autant passer par un redémarrage :

$ sudo systemctl reload sshd

La commande reload offre une manière plus gracieuse de recharger la configuration d'un service. Pour vous entraîner, reprenez l'exemple précédent en bloquant et en autorisant successivement l'accès distant pour l'utilisateur root. Cette fois-ci, utilisez reload au lieu de restart.

Activer un service au démarrage de la machine

La commande systemctl est un véritable couteau suisse qui gère l'initialisation et les services de la machine. Jetez un coup d'oeil sur la page de manuel systemctl(1) ; vous serez sans doute surpris par la pléthore d'options existantes. Là comme ailleurs, nous n'allons pas nous décourager face à l'abondance ; nous nous contentons de mettre un pied devant l'autre.

Affichez les services installés et actifs. Notez en passant que vous avez le droit d'effectuer cette opération en tant que simple utilisateur :

$ systemctl list-units --type service
UNIT                 LOAD   ACTIVE SUB     DESCRIPTION
auditd.service       loaded active running Security Auditing Service
chronyd.service      loaded active running NTP client/server
crond.service        loaded active running Command Scheduler
dbus.service         loaded active running D-Bus System Message Bus
firewalld.service    loaded active running firewalld - dynamic firewall daemon
...

Repérez le service OpenSSH dans la liste. Éventuellement, filtrez les résultats :

$ systemctl list-units --type service | grep sshd
sshd.service         loaded active running OpenSSH server daemon

L'option list-unit-files affiche l'ensemble des services installés, indépendamment de leur état :

$ systemctl list-unit-files –-type service
UNIT FILE                           STATE
auditd.service                      enabled
autovt@.service                     enabled
blk-availability.service            disabled
brandbot.service                    static
chrony-dnssrv@.service              static
chrony-wait.service                 disabled
chronyd.service                     enabled
...

Là aussi, repérez sshd.service dans la liste :

$ systemctl list-unit-files –-type service | grep sshd
sshd-keygen.service                 static
sshd.service                        enabled
sshd@.service                       static

Désactivez le service en utilisant l'option disable. Vous vous doutez probablement que ce genre d'opération requiert certains privilèges :

$ sudo systemctl disable sshd

Notez bien que le service n'est pas arrêté pour autant :

$ ps ax | grep -v grep | grep sshd
 1267 ?        Ss     0:00 sshd: microlinux [priv]
 1271 ?        S      0:00 sshd: microlinux@pts/0
 1528 ?        Ss     0:00 /usr/sbin/sshd -D

L'option status est bien plus pratique pour afficher l'état d'un service :

$ systemctl status sshd
● sshd.service - OpenSSH server daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; ...)
   Active: active (running) since Sat 2021-05-29 11:34:03 CEST; 9min ago
     Docs: man:sshd(8)
           man:sshd_config(5)
 Main PID: 1020 (sshd)
   CGroup: /system.slice/sshd.service
           └─1020 /usr/sbin/sshd -D

Quelle est donc la portée de la directive disable ? Pour en avoir le coeur net, redémarrez la machine et affichez l'ensemble des services :

$ systemctl list-units –-type service
$ systemctl list-unit-files –-type service

Repérez sshd.service dans l'affichage des résultats des deux commandes, puis vérifiez son état :

$ systemctl status sshd

En effet, la directive disable n'a pas arrêté le service OpenSSH. Elle a juste empêché son lancement au prochain démarrage.

Inversement, la directive enable active le lancement du service au prochain démarrage :

$ sudo systemctl enable sshd

Les cibles systemd

Les cibles systemd (ou targets) représentent les différents modes opératoires de notre système. Elles permettent de démarrer une machine avec juste les services requis pour une tâche définie.

$ systemctl list-units --type target
UNIT                  LOAD   ACTIVE SUB    DESCRIPTION
basic.target          loaded active active Basic System
...
multi-user.target     loaded active active Multi-User System
...
network.target        loaded active active Network
...
$ systemctl get-default
multi-user.target

La cible multi-user.target représente ici l'état final de notre système au démarrage. Les autres cibles comme basic.target ou network.target constituent autant d'étapes intermédiaires pour atteindre cet état final.

Dans la pratique quotidienne, nous aurons essentiellement affaire à deux cibles :

  • multi-user.target

  • graphical.target

Pour les opérations de dépannage, nous utiliserons les deux cibles suivantes :

  • rescue.target

  • emergency.target

La distinction entre multi-user.target et graphical.target a un sens sur les machines dotées d'un environnement graphique, comme les postes de travail ou les stations de travail. Sur les serveurs sans environnement graphique, on définira multi-user.target comme cible par défaut.

Démarrer en mode de secours

Les cibles rescue.target et emergency.target servent à dépanner un système qui ne démarre pas normalement. En l'occurrence, le démarrage s'effectue avec un nombre de services réduit et permet à l'administrateur root d'ouvrir une console pour chercher la cause de la panne.

  • Redémarrez la machine.

  • Lorsque l'écran du chargeur de démarrage GRUB s'affiche, appuyez sur la touche E (edit).

  • Naviguez dans les paramètres de démarrage avec les touches fléchées.

  • Repérez la ligne avec les paramètres du kernel. Elle commence par linux16 /vmlinuz-3.10.0-quelquechose et se termine par des options de démarrage comme rhgb et quiet.

  • Ajoutez l'option systemd.unit=rescue.target à la fin de cette ligne. Le clavier est en QWERTY américain par défaut, vous devrez donc tâtonner un peu.

  • Démarrez en utilisant la combinaison de touches Ctrl+X.

  • Lorsque l'invite de commande vous affiche Welcome to emergency mode, fournissez le mot de passe root pour ouvrir une console.

En temps normal – c'est-à-dire en mode multi-user.target – notre installation minimale lance pas moins de trente-sept services. Voyons comment les choses se présentent maintenant :

# systemctl list-units --type service
...
19 loaded units listed.

Nous constatons que le mode de secours n'affiche plus que dix-neuf services actifs, soit près de la moitié du mode normal. Si cela ne vous semble pas si minimal que ça, sachez que nous pouvons faire mieux.

Réitérez l'expérience précédente en éditant les paramètres de démarrage de GRUB, mais en remplaçant rescue.target par emergency.target.

L'invite de commande Welcome to emergency mode reste la même et vous devez fournir le mot de passe root comme vous l'avez fait auparavant pour ouvrir une console. C'est le nombre de services chargés qui fait la différence :

# systemctl list-units --type service
...
2 loaded units listed.

Cette fois-ci, nous sommes bien passés en mode "minimum syndical". Rien ne tourne sur notre machine en dehors du shell de secours (emergency.service) et des fichiers journaux (systemd-journald.service) du système.

Changer de cible à la volée

Admettons que nous souhaitions basculer du mode de fonctionnement normal multi-user.target vers le mode de secours rescue.target. Nous pouvons le faire directement, sans passer par un redémarrage et la modification des options du kernel dans GRUB :

$ sudo systemctl isolate rescue.target

Le système fait mine de redémarrer, mais au bout de quelques secondes, vous vous retrouvez confronté à l'invite du mode de secours :

Welcome to emergency mode!

Une fois que vous vous êtes connecté à la console de secours, procédez à l'inverse pour basculer directement vers le mode de fonctionnement normal :

# systemctl isolate multi-user.target

Afficher l'état du système

Est-ce qu'il y a moyen de savoir si tout s'est bien passé ? Est-ce que tous les services ont été lancés comme prévu ? C'est la directive status qui nous le dira.

$ systemctl status
● linuxbox.microlinux.lan
    State: running
     Jobs: 0 queued
   Failed: 0 units
...

À quoi ressemblerait un échec au démarrage ? Je vais utiliser une astuce pour vous en faire une simulation.

  • Redémarrez la machine.

  • Éditez les options de GRUB et démarrez avec le paramètre systemd.unit=emergency.target.

  • Connectez-vous à la console de secours minimale.

  • Basculez directement vers le mode de fonctionnement normal avec systemctl isolate multi-user.target.

Une fois que j'ai effectué cette manipulation, j'affiche l'état de mon système :

$ systemctl status
● linuxbox.microlinux.lan
    State: degraded
     Jobs: 0 queued
   Failed: 1 units
...

Le statut degraded apparaît en rouge et me suggère qu'il y a eu un problème quelque part... mais où ? C'est l'option --failed qui me le dira :

$ systemctl --failed
  UNIT                           LOAD   ACTIVE SUB    ...
● systemd-vconsole-setup.service loaded failed failed ...

Je tente de démarrer manuellement ce service :

$ sudo systemctl start systemd-vconsole-setup

J'affiche à nouveau l'état du système :

$ systemctl status
● linuxbox.microlinux.lan
    State: running
     Jobs: 0 queued
   Failed: 0 units
...

Apparemment, tout est rentré dans l'ordre.

Définir la cible par défaut

En temps normal – c'est-à-dire si nous ne modifions pas les paramètres de démarrage de GRUB – notre système démarre en mode multi-user.target :

$ systemctl get-default
multi-user.target

Je peux modifier la cible par défaut :

$ sudo systemctl set-default rescue.target

Au prochain redémarrage, le système m'affichera directement l'invite du mode de secours :

Welcome to emergency mode!

Le mode de secours rescue.target correspond désormais au mode de fonctionnement "normal" de ma machine :

# systemctl get-default
rescue.target

Pour redéfinir la cible multi-user.target comme mode de fonctionnement par défaut, je dois invoquer la commande suivante :

# systemctl set-default multi-user.target

Basculer entre les cibles sur un poste de travail

Dans la pratique quotidienne, on utilisera systemctl set-default et systemctl isolate principalement sur les postes de travail ou les stations de travail pour basculer entre le mode graphique (graphical.target) et le mode texte (multi-user.target).

Lorsque je dois changer une carte graphique dans un poste client, je commence par basculer vers le mode texte :

$ sudo systemctl set-default multi-user.target
$ sudo systemctl isolate multi-user.target

Une fois que j'ai apporté les modifications nécessaires à mon système, je teste d'abord si l'affichage graphique fonctionne correctement :

$ sudo systemctl isolate graphical.target

Si tout se passe comme prévu, je redéfinis le mode graphique par défaut :

$ sudo systemctl set-default graphical.target

Dans ce contexte, le mode multi-user.target est considéré comme une sorte de mode de secours qui me permet de manipuler mon poste de travail sans affichage graphique.

Éteindre et redémarrer la machine

Tout comme pour le démarrage, le système doit suivre une certaine procédure pour arrêter tous les services. L'extinction du système nécessite de tuer les processus dans un ordre cohérent et de faire le ménage dans les systèmes de fichiers avant l'arrêt des disques. C'est la commande halt qui s'en charge :

$ sudo halt -p

L'option -p (poweroff) se charge d'éteindre la machine lors de l'arrêt du système. Consultez la page de manuel halt(8) pour en savoir plus.

La commande reboot a le même effet que halt, au détail près que la machine redémarre au lieu de s'éteindre :

$ sudo reboot

Alternativement, nous pouvons invoquer systemctl avec les options respectives poweroff et reboot pour arrêter et redémarrer le système :

$ sudo systemctl poweroff

Lorsque je suis directement connecté à ma console, je peux également utiliser la combinaison de touches Ctrl+Alt+Del pour redémarrer.

Les utilisateurs de systèmes Microsoft Windows seront probablement bien familiarisés avec la combinaison de touches Ctrl+Alt+Del, qui sert à afficher un mot de leur sponsor en cas de plantage d'une application. Sachez que, sous Linux, il s'agit là du raccourci clavier normal pour redémarrer une machine en mode console.

Un peu de contexte historique

Les lecteurs de mon ouvrage Débuter avec Linux paru en 2017 et basé sur Slackware Linux ont eu l'occasion de découvrir le système d'initialisation BSD. Ce système "brut de décoffrage" reste fidèle à la philosophie Unix aussi bien qu'au principe KISS (Keep It Simple Stupid) et se base sur une série de scripts shell pour gérer les services et les niveaux d'exécution.

Red Hat Enterprise Linux, Oracle Linux et Debian ont longtemps utilisé la procédure System V, avec des niveaux d'exécution organisés différemment. D'autres systèmes d'initialisation ont vu le jour petit à petit, comme Upstart, développé par Canonical et adopté pendant quelque temps par Ubuntu et Fedora, ou encore OpenRC, utilisé par Gentoo depuis ses débuts. Actuellement, l'écrasante majorité des distributions a décidé d'adopter systemd, une alternative à System V spécifiquement conçue pour le noyau Linux.

L'adoption de systemd a suscité une série de controverses sans précédent dans le monde du libre. En résumé, les objections ne portent pas tant sur ses mérites en tant que système d'initialisation, mais sur le fait qu'il s'est imposé de force au détriment des solutions alternatives en s'étendant de façon tentaculaire dans des domaines qui n'ont plus rien à voir avec l'initialisation à proprement parler, sans oublier qu'il casse volontairement la compatibilité Posix avec les systèmes non-Linux comme la famille des BSD.

Quoi qu'il en soit, systemd a bel et bien gagné la bataille et s'est progressivement imposé un peu partout. En dépit de son côté "usine à gaz", il constitue une solution robuste qui offre quelques fonctionnalités fort pratiques pour les administrateurs système, sans oublier le mérite d'abolir les différences inutiles entre les distributions Linux.


La rédaction de ces cours demande du temps et des quantités significatives de café espresso. Vous appréciez cette formation ? Offrez un café au formateur.