Admin/Systemd/Brief
Gérer les Services avec systemctl
Gestion basique
Systemd est un gestionnaire de service. C'est le tout premier processus (PID 1) a être lancé et aussi le seul a être lancé par le noyau. Il doit donc assurer toute l’initialisation du système, le lancement des différents services et des systèmes permettant la connexion des utilisateurs. De plus il doit gérer les processus orphelins afin qu'il ne deviennet pas des processus zombies.
Il permet de lancer les processus, de les arrêter, de les relancer, bref, d'en assurer un suivi.
C'est aussi un gestionnaire de session. Il permet l'utilisation du même matériel en passant d'une session (~loging) à une autre sans que cela pose de problème. Il permet encore de gérer les points de montage qu'ils soient automatiques ou non.
C'est le successeur du gestionnaire de service SysVinit (init System V) et peut aussi remplacer xinetd, cron, syslog. La consultation des logs se fait avec Journalctl. Il a comme avantages:
- Il démarre moins de choses
Le démarrage d'un service est soumis à son utilité (ex le service de gestion du bluetooth ne deviend utile que lorsqu'un périphérique bluetooth s'enregistrera sur DBUS). Ce mode de fonctionnement ressemble à inted et xinetd. - Il démarre les services en parrallèle (en respectant un arbre de dépendances).
Systemd dispose d'une notion d'unité (unit in english).
- service : les plus simples correspondent à des services. Peuvent être démarrés, coupés, redémarrés, reconfigurés (start/stop/restart/reload), comme on le fait habituellement avec les scripts dans /etc/init.d/ ;
- socket : correspond à une socket, que ce soit de type UNIX, de type Internet, de type fichier ; chaque socket a un service correspondant ;
- mount : un système de fichiers ; ces unités viennent en plus du fichier /etc/fstab qui est utilisé directement ;
- swap : pour les partitions d’échange ;
- automount : un système de fichiers monté à la demande ;
- target : une macro‐unité qui permet de grouper plusieurs unités, par exemple multi-user.target ou bluetooth.target ;
- snapshot : comme target, ce sont des unités qui peuvent être utilisées pour sauver l’état actuel des services et les restaurer par la suite, par exemple avant de passer en veille ;
- device : un périphérique dans le système Linux ; peut être une source de dépendance via udev ;
- timer : activations à la sauce cron, en fonction de la date ;
- path : sert pour l’activation basée sur la présence ou la création de fichiers ou répertoires.
Les services sont un type d'unité.
- Démarrage d'un service. C'est l'équivalent de <app>service myservice start</app>
systemctl start myservice.service
- Arrêt d'un service. C'est l'équivalent de <app>service myservice stop</app>
systemctl stop myservice.service
- Ajout d'un service au démarrage. C'est l'équivalent de <app>chkconfig myservice on</app>
systemctl enable myservice.service
- Suppression d'un service au démarrage. C'est l'équivalent de <app>chkconfig myservice off</app>
systemctl disable myservice.service
Avantages
- Pour chaque service, il est possible de régler de nombreux paramètres : limites, répertoire racine (chroot), umask, priorité, paramètre « OOM killer » (out of memory), les classes et les priorités d’ordonnancement et d’entrées‐sorties, l’affinité processeur, l’utilisateur, les groupes, les répertoires accessibles et les modes d’accès, les capacités, le répertoire temporaire, le réglage des cgroups…
- Les flux stdout et stderr peuvent être redirigés vers le service de journalisation, vers « /dev/kmsg », vers un terminal ou vers un fichier.
- Intégration de SELinux, des « TCP wrappers », des modules d’authentification PAM.
- Chaque service a son propre cgroup.
- Chaque connexion via un terminal est aussi placée dans son propre cgroup, ce qui permet de fermer complètement une session et d’isoler un peu mieux les utilisateurs (processeur, mémoire).
- La syntaxe des fichiers de configuration suit celle bien connue des fichiers « .desktop ».
- Le système est compatible avec les anciens scripts SysVinit. Les informations LSB et chkconfig (de Red Hat) ainsi que celles de Debian et d’OpenSUSE sont utilisées lorsqu’elles sont disponibles. Sinon, l’ordre de démarrage dans « /etc/rc.d/ » est utilisé. systemd est également capable de lire le fichier PID pour retrouver un service. Ces données permettent d’émuler une configuration classique SysVinit, facilitant la transition.
- Le fichier « /etc/fstab » est également lu comme s’il s’agissait d’un fichier de configuration de systemd.
- Les fichiers natifs systemd masquent ces émulations, permettant de faire des paquets compatibles avec les deux systèmes, le nouveau masquant l’ancien si nécessaire.
- Il existe un système de modèles pour éviter de dupliquer une configuration (par exemple, pour les 6 getty des terminaux virtuels habituellement lancés).
- systemd fourni une couche de compatibilité avec « /dev/initctl » permettant d’utiliser les vieux binaires, tels que shutdown ou reboot. Les ordres sont transmis à systemd via D-Bus. Il prend en charge également kexec qui permet de relancer le noyau Linux.
- Il gère utmp et wtmp, les journaux système enregistrant les connexions.
- Chaque processus lancé est tracé par son heure de démarrage, de fin, son PID et son code de retour ; permettant d’analyser les anomalies.
- systemd est capable de se ré‐exécuter lui‐même, afin de faire une mise à jour, ou de passer d’un processus provenant d’un « RAM‐disque » d’amorçage (initrd) au système final. Tout l’état courant est migré d’un processus à l’autre.
- La mise en place des systèmes de fichiers virtuels est directement prise en charge par systemd (/proc, /sys, /dev), binfmt_misc et HugeTBLfs sont gérés via autofs, ce qui évite d’avoir à les configurer en root ou à charger le module correspondant.
- De nombreuses petites fonctions sont prises en charge directement sans passer par le lancement d’un script : définir le nom de la machine, sauver / restaurer les données aléatoires, initialiser la localisation, nettoyer les répertoires temporaires, configurer la console, le clavier, charger des modules. Cela a pour conséquence d’unifier ces fichiers de configuration sur toutes les distributions utilisant systemd.
- Il existe un mode de démarrage interactif qui permet de confirmer chaque lancement de service en passant au noyau le paramètre « systemd.confirm_spawn=1 ».
- systemd gère le readahead qui permet d’optimiser les lectures disque au démarrage en pré‐chargeant les blocs qui vont être nécessaires par la suite (en se basant sur un enregistrement d’un démarrage précédent).
Inconvénients
- Utilisation de programme pour chaque tâche d'administration: gestion des services, lecture des journaux de logs, etc…
- Systemd est plutôt invasif. Il n’entend pas se contenter de gérer seulement le lancement des démons, mais également de prendre en charge l’authentification, la gestion de l’énergie etc … Ce qui de fait s’oppose quelque peu à la philosophie Unix qui dit qu’il vaut mieux plusieurs petits programmes qui ne s’occupent que d’une tâche à la fois bien, plutôt qu’une pieuvre qui voudrait tout faire mal (« do one thing, but do it well »). Certains l’appellent même le deuxième Kernel.
Gestion particulière
Multi-instances
Certains services ont de multiples déclinaisons: un client et un serveur peuvent être activés sur la même machine, une interface réseau virtuelle dupliquée, etc ...
Systemd implémente pour eux une variable dans le nom du fichier afin de les différencier.
ex: OpenVPN: client est le nom du fichier de configuration à charger dans <path>/etc/openvpn</path> (sans l'extension .conf)
systemctl start openvpn@client.service
Service associé à une socket
Certain services nécessite l'écoute préalable sur une socket et ne sont démarrés que lors d'une connexion sur celle-ci, à la manière de inetd/xinetd.
ex: git-daemon: Seul l'écoute sur la socket est démarré. Le service associé sera démarré à la connexion. De plus, le service ne peut être démarré manuellement (le fichier unit est un template, il comporte un @ dans son nom)
systemctl start git.socket
Modification de la configuration d'un daemon
Après avoir modifier une configuration Unit, il est nécessaire d'en informer systemd avec la commande
systemctl --system daemon-reload
Lister les services
Pour lister les services, avec leur état actuel et une brève description (équivalent à chkconfig --list)
systemctl --full --type=service
Pour lister les fichiers unit définissant un service sur le système (équivalent à ls /etc/init.d/)
systemctl list-unit-files --type=service
Confinement
Sur la plupart des systèmes GNU/Linux, le nombre de processus en fonctionnement est important. Il est de plus en plus difficile de savoir quel processus fait quoi et d’où il vient. Certains ont même plusieurs processus de travail qui surchargent la sortie de <app>ps</app> avec beaucoup de processus additionnels souvent difficiles à reconnaître. Ça se complique encore avec les démons qui lancent des processus tiers, comme Apache le fait avec les processus CGI ou cron avec les tâches utilisateurs.
Souvent, le seul workaround consiste à regarder l’arbre d’héritage des processus tel qu’il est donné par <app>ps xaf</app>, mais ce n’est généralement pas fiable. Les processus orphelins sont réassignés au processus 1 et, par conséquent, toutes les informations d’héritage sont perdues. En faisant deux forks() successifs, un processus peut perdre sa relation avec celui qui l’a lancé (c’est supposé être une fonctionnalité et cela repose sur le comportement traditionnel de création de démons sous UNIX). Par ailleurs, les processus peuvent à leur convenance changer leur nom grâce à PR_SETNAME ou en modifiant argv[0], rendant ainsi leur reconnaissance plus difficile.
Avec systemd, chaque processus engendré est placé dans un groupe de contrôle (cgroup) nommé d’après le service. Les groupes de contrôle, du point de vue le plus élémentaire, sont simplement des groupes de processus qui peuvent être classés hiérarchiquement et étiquetés individuellement. Quand des processus engendrent d’autres processus, ces enfants sont automatiquement membres du groupe de contrôle de leur parent. Quitter un groupe de contrôle n’est pas possible pour un processus sans privilège. C’est pourquoi les groupes de contrôle peuvent être utilisés pour étiqueter tous les processus d’un service efficacement et indépendamment du nombre de forks() ou de renommages. En allant plus loin, les groupes de contrôle peuvent être utilisés pour tuer proprement un service et tous les processus qu’il a créés, sans exception.
systemd-cgls ├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 20 ├─system.slice │ ├─avahi-daemon.service │ │ ├─1149 avahi-daemon: running [didier.local │ │ └─1164 avahi-daemon: chroot helpe │ ├─dbus.service ...