systemd est un démon destiné à remplacer l’ancien système de démarrage init. Il a pour but d’offrir un meilleur cadre pour la gestion des dépendances entre services, de permettre le chargement en parallèle des services au démarrage, et de réduire les appels aux scripts shell.
Il est mis en œuvre dans un certain nombre de distribution standard – Fedora, openSUSE, Arch, RHEL, CentOS, etc.
Cet article a pour base une publication de Carla Schroder sur linux.com
C’est quoi systemd ?
Un démon !
systemd est un démon de gestion système nommé conformément à la convention UNIX qui consiste à ajouter un «d» à la fin du nom du démon. Cela permet de les reconnaître facilement.
Initialement, il a été libéré sous la licence GNU General Public, Le projet a été lancé par Lennart Poettering en 2010 et publié sous licence GNU LGPL. Le nom de ce programme vient de « system daemon » : le daemon du système. Comme init, systemd est le parent de tous les autres processus, directement ou indirectement. Il est le premier processus lancé au démarrage donc il se voit généralement attribuer un « pid = 1″.
Comment démarre le système ?
d’après http://linuxfr.org/news/systemd-l-init-martyrise-l-init-bafoue-mais-l-init-libere – CC by SA
Lorsqu’un ordinateur démarre, il initialise les différents composants de l’ordinateur (processeur, mémoire vive, disque dur, carte graphique, etc.) et effectue quelques vérifications basiques, puis démarre le cœur du système d’exploitation : le noyau (ici, Linux). En effet, c’est la partie qui communique directement avec les périphériques comme le clavier, la souris, la mémoire ou l’écran et permet leur utilisation.
Lorsque le noyau est chargé, l’ordinateur n’est pas encore prêt à l’emploi. Le noyau délègue au système d’initialisation le lancement du reste du système, selon la configuration établie par l’administrateur. Il lance les services d’arrière-plan (montage des périphériques de stockage, configuration du réseau, messagerie…) et l’interface utilisateur, qu’elle soit graphique ou pas. Le système d’initialisation possède aussi une autre fonction : récupérer les processus qui sortent de leur session. En effet, dans tous les Unix-like—et cela inclut GNU/Linux—tous les processus doivent avoir au moins un processus père, sauf le tout premier processus lancé (PID 1). Si un processus renie son père (on dit qu’il est démonisé), le noyau le rattache alors au premier processus.
Hormis le noyau, il est donc le premier processus lancé sur la machine (ce qui explique l’appellation « PID 1 » — « processus n°1 ») et le dernier à s’arrêter, car il contrôle tous les autres. Par conséquent, le système d’initialisation est un composant critique du système car s’il ne fonctionne pas, la machine ne démarre pas. D’où sa robustesse requise.
Jusqu’à récemment ce programme était souvent SysVinit, mais des remplaçants, plus ou moins compatibles, se sont multipliés ces dernières années, comme Upstart qui est l’init par défaut d’Ubuntu. Un init de type SysV fonctionne comme suit : il lit le fichier /etc/inittab qui lui indique quoi faire à un niveau d’exécution (runlevel) particulier, puis il démarre, redémarre ou arrête automatiquement les services selon le niveau choisi par l’utilisateur.
La syntaxe de ce fichier n’étant pas turing complète, les administrateurs ont préféré déléguer l’essentiel du démarrage à des scripts rc nommés dans ce fichier et appelés par init.
Ces scripts sont aujourd’hui décriés à cause du travail dupliqué entre les distributions, de la difficulté réelle ou supposée de les maintenir et de leurs limites. Sont-elles supposées ou avérées ? Là est toute la question ! Quelques exemples :
- tous ne sont pas, par exemple, forcément compatibles avec des composants tels que selinux (ou autre LSM à la mode) ;
- il est difficile de lancer un service uniquement suite à un événement. Par exemple, lors du branchement d’une clé USB ;
- il est difficile de s’assurer qu’un service (par exemple, sshd) sera relancé automatiquement en cas d’arrêt.
Le système d’init nécessite un travail d’intégration important dans la distribution ; il ne peut donc pas, la plupart du temps, être changé facilement par l’utilisateur.
Ca change quoi, systemd ?
Le projet systemd est écrit avec le langage de programmation C. Il s’agit d’une collection de logiciels sous forme de binaires. Le pilotage des services se fait grâce à des fichiers de configuration.
À première vue, cela ressemble à SysV (écrit en C, formé de trois exécutables et configuré par le fichier « inittab »), mais la grande différence est que SysV suit une approche minimaliste qui déplace une grande partie de l’initialisation des services dans des programmes écrits en Shell et utilisant des bibliothèques externes (par exemple, « start-stop-daemon » pour l’init Debian). À contrario, systemd implémente un large éventail d’actions afin de décourager l’utilisation de scripts de lancement. En pratique, un service SysV pour sshd a pour élément central un script de quelques centaines de lignes (script Shell qui peut être utilisé indépendamment de l’init), alors que sous systemd le service sera généralement piloté par un fichier texte d’une dizaine de lignes (dans une syntaxe spécifique à systemd).
On vante souvent la simplicité des anciens systèmes d’init : en effet, quoi de plus simple que des fichiers textes exécutables dont on peut lire l’exécution ligne par ligne ?
En éditant ces fichiers, on a une maîtrise totale du démarrage de l’ordinateur (à partir du moment où l’on est capable de comprendre le code). Mais modifier le système d’init en lui-même peut poser problème lors de mises à jour ou simplement parce que ce code n’a pas été testé.
systemd remplit les mêmes fonctions que les précédents systèmes, mais il met l’accent sur la simplicité d’utilisation et sur une maîtrise du système plus poussée et moins éparpillée, ce qui est parfois vu comme l’opposé de la philosophie Unix.
Ainsi, beaucoup de choses qui nécessitaient auparavant de modifier des scripts Shell existent maintenant sous la forme d’un simple paramètre dans un fichier. Le comportement est codé dans systemd ce qui permet de mutualiser beaucoup de code et de rendre les fichiers souvent beaucoup plus courts.
Pour la plupart des gens, utiliser systemd ou SysVinit ne fait aucune différence, y compris pour la vitesse de démarrage ; pour bidouiller, tout dépend des outils que l’on maîtrise, soit les outils systemd et leur syntaxe de configuration, soit la programmation Shell, les outils de suivi de processus et la configuration SysV.
systemd en pratique
Un peu d’histoire
Qu’on le veuille ou non systemd est là. Et comme je l’ai souvent dit le rôle du technicien n’est pas de critiquer les choix qui ont été faits (même s’il a le droit de râler !) mais d’utiliser au mieux les outils mis à sa disposition. Et si ça ne lui plait vraiment pas, libre à lui de créer une nouvelle distribution ou une nouvelle carte mère qui fera ce qu’il souhaite… C’est d’ailleurs ce qu’on fait les dissidents de Debian qui ont créé Devuan (=Dev One), une Debian sans systemd.
systemd est controversée pour plusieurs raisons : Il remplace quelque chose que beaucoup d’utilisateurs de Linux n’estiment pas devoir être remplacé, et le comportement des développeurs de systemd n’a pas conquis les cœurs et les esprits. c’est plutôt le contraire, comme en témoigne le fameux fil LKML dans lequel où Linus Torvalds interdit l’accès au noyau Linux à Kay Sievers, développeur de systemd.
Pendant des années Linux a fonctionné avec SysVInit et BSD init. Puis sont venus les add-on les gestionnaires de services, comme les commandes service et chkconfig qui étaient censées rendre la gestion des services plus aisée, mais qui n’étaient que des choses supplémentaires à maîtrisersans que cela ne rende la tâche plus facile, juste un peu plus complexe.
Ensuite vinrent Upstart et systemd avec toutes sortes d’extension alambiquées pour maintenir la compatibilité avec SysVInit. Ce qui part d’un bon sentiment… Mais bon courage pour comprendre comment ça fonctionne. Maintenant Upstart a pris sa retraite au profit de systemd, à partir d’Ubuntu 14.10.
Ca fait toujours peur quand les développeurs commencent à tritouiller les sous-systèmes clés dans Linux, parce que nous sommes un peu coincé avec tout ce qu’ils imposent. Si nous n’aimons pas une application particulière, ou un l’environnement de bureau, ou une commande il y a toujours plusieurs alternatives et il est facile à utiliser quelque chose d’autre. Mais les sous-systèmes essentiels ont des accroches profondes dans le noyau, un tas de scripts de gestion, et des dépendances de paquets logiciels, alors les remplacer n’est pas du tout facile.
La morale de cette histoire (larirette…) c’est que les choses changent, les ordinateurs deviennent inévitablement de plus en plus complexes, et finalement tout ça fonctionne… ou pas ! Mais nous devons nous habituer à ne pas pouvoir façonner les événements selon notre propre volonté.
Premiers pas avec systemd
Red Hat est l’inventeur et le premier promoteur de systemd, donc les meilleures distributions pour jouer avec systemd sont Red Hat Enterprise Linux, ou les clones de RHEL comme CentOS et Scientific Linux, et bien sûr le bon vieux Fedora Linux, qui embarque toujours la dernière version.
Les utilisateurs expérimentés de RH peuvent toujours utiliser service
et chkconfig
en RH 7, mais il est grand temps de les remplacer par les services natifs. systemd les a remplacés, et service
et chkconfig
ne prennent pas en charge les services natifs de systemd.
Notre bien-aimé /etc/inittab n’est plus.
A la place, nous avons un répertoire /etc/systemd/system/ rempli de liens symboliques vers des fichiers situés dans /usr/lib/systemd/system/.
C’est ce répertoire qui contient les scripts d’initialisation : pour lancer un service au démarrage, il doit être lié à /etc/systemd/system/. La commande systemctl le fait pour vous lorsque vous activez un nouveau service, comme je le fais dans cet exemple pour tightvncserver :
Installer tightvncserver
On commence comme d’habitude par mettre à jour la distribution :
sudo apt-get update sudo apt-get upgrade
On peut passer à l’installation de tightvncserver :
pi@raspberrypi:~ $ sudo apt-get install tightvncserver
Lancer tightvncserver pour vérifier qu’il est bien installé et fonctionne :
pi@raspberrypi:~ $ vncserver :1 You will require a password to access your desktops. Password: Warning: password truncated to the length of 8. Verify: Would you like to enter a view-only password (y/n)? n New 'X' desktop is raspberrypi:1 Creating default startup script /home/pi/.vnc/xstartup Starting applications specified in /home/pi/.vnc/xstartup Log file is /home/pi/.vnc/raspberrypi:1.log
Voyons voir si ça marche
On peut maintenant lancer VNCviewer sur le PC pour voir si on se connecte bien au RasPi :
Cliquez sur Connexion
Tapez le mot de passe que vous aviez saisi sur le Raspberry Pi (pour faire original j’avais mis… raspberry )
Créer le service sous systemd
Créez un fichier /etc/systemd/system/vncserver@.service
pi@raspberrypi:~ $ sudo nano /etc/systemd/system/vncserver@.service
avec le contenu suivant :
[Unit] Description=Service de bureau à distance (VNC) After=syslog.target network.target [Service] Type=forking User=pi PAMName=login PIDFile=/home/pi/.vnc/%H:%i.pid ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1 ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280x800 :%i ExecStop=/usr/bin/vncserver -kill :%i [Install] WantedBy=multi-user.target
Modifiez éventuellement les paramètres dans le fichier. puis lancez l’installation du logiciel :
pi@raspberrypi:~ $ sudo systemctl daemon-reload && sudo systemctl enable vncserver@1.service Created symlink from /etc/systemd/system/multi-user.target.wants/vncserver@1.service to /etc/systemd/system/vncserver@.service.
systemctl indique en retour qu’il a bien créé le lien symbolique.
Vous pouvez maintenant redémarrer le Raspberry Pi :
pi@raspberrypi:~ $ sudo reboot
On peut vérifier que tightvncserver a bien été lancé :
pi@raspberrypi:~ $ systemctl UNIT& LOAD ACTIVE SUB DESCRIPTION ... vncserver@1.service loaded active running Service de bureau à distance (VNC)
Il reste un petit défaut : dans le fenêtre de VNCviewer, le curseur de souris prend la forme d’une croix noire. Une modification dans le fichier /home/pi/.vnc/xstartup permet de retrouver le curseur classique (une flèche orientée vers la gauche) :
Remplacez
xsetroot -solid grey
par
xsetroot -solid grey -cursor_name left_ptr
et au prochain redémarrage, lorsque vous reconnecterez VNCviewer, vous retrouver votre curseur habituel.
Tout ça c’est bien joli, mais tu nous explique un peu ?
Si vous voulez… On va faire ça ligne par ligne en prenant comme exemple le fichier vncserver@.service que nous avons créé ci-dessus. Je vous dis ce que j’en ai compris/trouvé sur les pages d’aide… N’hésitez pas à me reprendre ou à compléter :
[Unit]
Le fichier xxx@.service peut comporter cette section [Unit], qui contient l’information générique de l’unité et ne dépend pas du type d’unité.
Description=Service de bureau à distance (VNC)
Cette chaîne libre décrit l’unité. Cette ligne est destinée à fournir des informations décrivant l’unité. La description doit signifier quelque chose pour l’utilisateur final. « Serveur Web Apache 2 » est un bon exemple, « serveur HTTP léger haute performance » est mauvais : trop générique ou encore « Apache2 » trop spécifique et dénuée de sens pour les gens qui ne connaissent pas Apache.
After=syslog.target network.target
After indique que le service actuel VNCserver ne sera démarré qu’après le démarrage effectif des services listés (et séparés par un espace)
[Service]
les fichiers des services doivent inclure une section « [Service] », comportant des informations sur le service et le sur processus qu’il supervise. Ces options sont documentées dans systemd.exec (5) et systemd.kill (5).de service sont les suivantes:
Type=forking
Si Type est défini comme forking, le processus configuré avec ExecStart= (ci-dessous) fera un appel à la fonction fork () lors de son démarrage. Le processus parent se termine quand le démarrage est fini et que tous les canaux de communication sont établis. L’enfant continue de fonctionner en tant que processus démon principal. C’est le comportement des démons UNIX traditionnels. Si ce paramètre est utilisé, il est recommandé d’utiliser l’option PIDFile= pour que systemd puisse identifier le processus principal du démon. systemd démarrera les unités suivantes dès l’arrêt du processus parent.
User=pi
Permet de désigner l’utilisateur qui lancera le processus
PAMName=login
Définit sous quel nom la session démarre. Si défini, le processus sera enregistré comme session PAM sous le nom de service spécifié. Ceci est utilisé en association avec l’option User= (ci-dessus).
PIDFile=/home/pi/.vnc/%H:%i.pid
Bon, ici la ligne est plus longue… Regardons en détail les différentes parties :
/home/pi/.vnc/ designe le chemin (l’endroit) où le fichier de PID sera enregistré.
%H:%i.pid est le nom du fichier avec %H le nom de la machine et %i le numéro de l’instance de l’unité.
Dans la pratique on trouve
pi@raspberrypi:~/.vnc $ ls passwd raspberrypi:1.log raspberrypi:1.pid xstartup
et dans le fichier raspberrypi:1.pid
pi@raspberrypi:~/.vnc $ cat raspberrypi:1.pid 562
Avec 562 qui est l’ID du processus.
ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1
Encore une ligne à rallonge !
ExecStartPre= c’est la commande qui sera exécutée avant ExecStart (on s’en serait douté !)
usr/bin/vncserver -kill:%i cette commande « tue » un bureau VNC qui aurait préalablement lancé par le serveur. Elle le fait en tuant le processus dont l’ID est stockée dans le fichier « /home/pi/.vnc/hôte: instance.pid » (voir ci-dessus)
/dev/null 2>&1 redirige toute sortie de cette commande vers un « trou noir » : Rien n’est affiché
ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280×800 :%i
Si le service est lancé avec start, cette ligne va lancer le serveur VNC avec une profondeur de couleur de 24 bits ( -depth 24), une taille d’écran de (-geometry 1280×800) sur l’instance :i%
ExecStop=/usr/bin/vncserver -kill :%i
Si le service est arrêté avec stop, cette ligne va « tuer » l’instance en cours
[Install]
WantedBy=multi-user.target
La section « [Install] » comporte des informations pour l‘installation de l’unité. Cette section n’est pas interprété par systemd lors de l’exécution. Elle est utilisée exclusivement par les commandes enable et disable de l’utilitaire systemctl lors de l’installation d’une unité.
WantedBy=multi-user.target
Les target de systemd ressemblent aux runlevel que nous avons connus précédemment. Ils portent un nom au lieu d’un numéro. Ici multi-user correspond au runlevel 3, c’est à dire le mode texte (non graphique) multi utilisateurs… Un lien symbolique est créé dans le répertoire .wants/ de chacune des unités répertoriées lorsque cette unité est installé avec systemctl enable. Le résultat est que l’unité actuelle sera lancé lorsque l’unité indiquée après WantedBy sera lancée.
Vous trouverez ci-dessous tout un tas de liens plus intéressants les uns que les autres si vous souhaitez aller plus loin dans la compréhension de systemd.
Et si je neveux plus utiliser VNCserver ?
Vous pouvez soit le dévalider
sudo systemctl disable vncserver@1.service
Soit l’enlever complètement
sudo systemctl remove vncserver@1.service
Et c’est tout ?
Non, bien sûr… systemd comprend bien d’autres options. Mais c’est peut être suffisant pour cet article, non?
Allez une dernière info : Comment faire pour démarrer, arrêter manuellement un service ?
# systemctl start [name.service] # systemctl stop [nom.service] # systemctl restart [nom.service] # systemctl reload [nom.service] $ systemctl status [nom.service]
Les quatre premières commandes fonctionnent avec root (en sudo), la dernière est accessible en utilisateur normal…
Par exemple si vous voulez arrêter le serveur VNC :
pi@raspberrypi:~ $ sudo systemctl stop vncserver@1.service
Conclusion
La migration vers systemd ne va pas se faire sans grognements. Vous trouverez sur la toile autant d’arguments en sa faveur qu’en sa défaveur. A mon avis, il faudra s’habituer, oublier des années de pratique de sysV.
Un regret quand même, c’est que le Raspberry Pi est destiné pour beaucoup à des débutants et le passage (discret) à systemd ne me semble pas avoir été assez accompagné par la Fondation, laissant bon nombre d’utilisateurs perplexes… un peu comme le changement de gestion du réseau confié maintenant à dhcpcd. Combien d’entre nous se sont démenés avec le fichier interfaces avant de s’apercevoir du changement ?
Sources
- https://www.linux.com/learn/tutorials/788613-understanding-and-using-systemd
- http://linuxfr.org/news/systemd-l-init-martyrise-l-init-bafoue-mais-l-init-libere
- Le blog de Nicolas Ledez
- L’article de Carla Schroder sur Linux.com – Sept 2014
- https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
- L’article de Avishek Kumar sur tecmint.com
- https://www.raspberrypi.org/forums/viewtopic.php?t=123457&p=830506
- http://linuxfr.org/news/systemd-pour-les-administrateurs-parties-3-4-et-5
- http://0pointer.de/public/systemd-man/systemd.special.html
- http://www.lanterne-rouge.info/article-que-signifie-dev-null-2-1-70233357.html
- https://wiki.archlinux.org/index.php/systemd
- http://www.freedesktop.org/software/systemd/man/systemd.unit.html
- http://www.freedesktop.org/software/systemd/man/systemd.service.html
- http://www.freedesktop.org/software/systemd/man/systemd.directives.html
- http://www.freedesktop.org/software/systemd/man/systemd.exec.html
- https://www.realvnc.com/products/open/4.1/man/vncserver.html