0

systemd mother fucker

Qué es ?

Systemd ou system daemon est un système d’initialisation à destination du noyau Linux. Il a été conçu pour offrir un paramétrage des services au démarrage, une meilleur gestion des dépendances entre ces services et réduire les appels aux scripts shell linux. Son homologue historique est System V, et on peux aperçevoir encore aujourd’hui de nombreux débats entre systemd et System V …

Au niveau des versions, on en est à la v238, disponible ici.

Pour connaître son numéro de version actuel :

$ systemd --version

Emplacement

System V

Pour system V, l’emplacement des scripts d’initialisation se situe dans /etc/init.d. Et on gère les services avec /etc/init.d/mon_service start ou alors avec la commande service, qui point sur le même chemin d’init.

systemd

Pour les fichiers de configuration de systemd, on trouve deux répertoires :

• Le premier, contenant la configuration par défaut dans /lib/systemd/system.

• Un second répertoire existe, /etc/systemd/system qui est utilisé pour stocker ces propres configurations/modifs’ personnelles. Ce répertoire contient des fichiers service sous forme de liens symboliques, pointant sur le répertoire /lib/systemd/system.

Placer ses propres modifications dans /etc/systemd/system évite de les voir écraser en cas de mises à jours système (le répertoire /lib contient toutes les libraires nécessaire pour le bon fonctionnement du système et l’exécution des commandes).

Lors du listage du répertoire /etc/systemd/system, on s’aperçois que les services présents sont des liens symboliques pointant vers /lib/systemd/system :

$ ls -al /etc/systemd/system/

lrwxrwxrwx 1 root root 35 déc. 23 15:22 display-manager.service -> /lib/systemd/system/lightdm.service

lrwxrwxrwx 1 root root 31 janv. 17 19:22 sshd.service -> /lib/systemd/system/ssh.service

Commandes en vrac

Services

Démarrer le service exemple

$ systemctl start exemple.service

Stopper le service exemple

$ systemctl stop exemple.service

Afficher le statut du service exemple (état, emplacement, temps d’activité, PID ..)

$ systemctl status exemple.service

Redémarrer le service exemple (stop puis start)

$ systemctl restart exemple.service

Redémarrer le service exemple en étant déja actif

$ systemctl condrestart exemple.service

Activer au démarrage le service exemple

$ systemctl enable exemple.service

Afficher les processus en cours d’exécutions avec leur PID sous forme d’arbre

$ systemctl status

Suspendre le système (mise en veille)

$ systemctl suspend

Vérifier si le service exemple est actif au démarrage du poste ou non

$ systemctl is-enabled exemple.service

Lister les services actifs au démarrage de l’OS

$ systemctl list-unit-files | grep enabled

Lister les services actuellement actifs

$ systemctl list-units -t service

Liste les dépendances du service exemple

$ systemctl list-dependecies exemple.service

Rechargement de systemd (nouveau fichier init par ex..)

$ systemctl daemon-reload

Analyser son temps de boot (chargement du kernel + espace utilisateur).

$ systemd-analyze

Dans le même genre, pour repérer les services ralentissant le démarrage du système

$ systemd-analyze blame

Logs

SystemD inclue également l’outil journalctl pour la journalisation (logs) de ses évènements.

Consulter les logs en temps réel

$ journalctl -f

Consulter les logs d’un services précis

$ journalctl --unit <mon_service>

Consulter les logs jusqu’au 03 Février 2019 à 10h00

$ journalctl --until "2019-02-03 10:00:00"

Consulter les logs depuis le  07 Février 2019 à 23h20

$ journalctl --since "2019-02-07 23:20:00"

On peut combiner cela avec un service précis

$ journalctl --since "2019-02-07 23:20:00" --unit <mon_service>

Étude d’un service

SSH

Un service basique : le serveur SSH.

$ systemctl status ssh

1. ● ssh.service – My Secure Shell Server 🙂

2. Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)

3. Active: active (running) since jeu. 2018-01-25 18:11:10 CET; 1h 16min ago

4. Process: 15781 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)

5. Main PID: 1201 (sshd)

6. CGroup: /system.slice/ssh.service

└─1201 /usr/sbin/sshd -D

1. Nom du service suivi de sa description (custom pour ma part).

2. Son statut (loaded) et son emplacement. Plus de détails sur le preset ici. L’administrateur peut faire le choix de sélectionner uniquement certaines unités à activer.

3. L’état du service, sa date de démarrage et son uptime.

4. C’est un peu flou. Ce numéro est utilise pour tout les autres processus qui auraient pu être démarré par le service avec ExecStartPre, ExecStartPost etc .. Plusieurs autres lignes lancés par le service AUTRES que le processus principal.

5. Le PID du processus lancé avec ExecStart. Retrouvable avec un $ ps -aux |grep num_pid

6. Le groupe de contrôle (allocation des ressources à un processus) en lien avec avec le systemd.slice.

Les composants d’un fichier service

[Unit]

Description= Description du service

Avec After=my_service.service, il ne se lanceras qu’une fois que my_service.service sera démarré, dans un deuxième temps donc. A contrario, il y a aussi Before=my_service.service

Requires= conditionne les dépendances. Si l’exigence de la ligne requires n’est pas respecté, alors le service ne démarrera pas.

[Service]

Temps d’attente avant la mise en service avec TimeoutStartSec=

ExecStart= indique la commande à exécuter au moment du lancement du service. Paramètre obligatoire.

On peut également trouvé TimeoutStopSec= (temps d’attente avant l’arrêt du service) et TimeoutSec= (Raccourcis pour définir en même temps la valeur de Start et Stop)

ExecStartPre= correspond aux commandes exécutées avant le démarrage du service. Au niveau de la syntaxe, c’est un chemin absolu à respecter.

ExecStop= indique la commande pour stopper le service.

Type= est facultatif, et permet d’indiquer le type de démarrage du processus. Plusieurs valeurs sont possibles, voici les principales :

simple : la valeur qui définis ExecStart= sera le processus principal du service. Il deviens actif immédiatement, même si il est encore en cours d’initialisation.

forking : lorsque le processus parent se termine, le processus enfant continue toujours à tourner : c’est un daemon.

oneshot : similaire à la valeur simple, le processus doit se terminer avant les unités de suivis. Il ne contient pas de ExecStart= mais un ExecStop=

StandardOutput= pour la sortie d’affichage (tty, logs ..)

RemainAfterExit= qui permet d’indiquer qu’une fois la commande de lancement exécutée (ExecStart), le service est toujours considéré comme actif. Et ceux jusqu’à l’arrêt (ExecStop) de ce service.

Restart= et l’argument associé permet d’indiquer le mode de fonctionnement du service si il crash, redémarre, arrêté ou si un délai d’attente définis (timeout) est atteint.

Au niveau des arguments principaux possible pour le Restart= :

– no : présent par défaut, le service ne sera pas redémarré

on-success : le service ne sera redémarré que lorsque le processus sera proprement terminé (code de sortie = 0)

on-failure : le service ne sera redémarré lorsque le processus sera terminé avec une erreur (code de sortie différent de 0)

always : Le service sera redémarré peu importe le fait qu’il se soit terminé proprement ou non.

[Install]

La section Install d’une unité est facultative et n’est pas interprétée par systemd. Son exécution ici se passera dans le niveau d’exécution multi-utilisateur au niveau des Runkevels 2, 3, 4 et 5.

Un runlevel correspond au niveau d’exécution du processus. Avec Debian, sept niveaux sont définis :

  • 0 – Arrêt du système
  • 1 – Simple utilisateur, mode minimal/maintenance
  • 2 à 5 – Mode multi-utilisateurs
  • 6 – Redémarrage système

Avec WantedBy= et l’argument multi-user.target, on indique à notre service d’agir dans la target multi-utilisateurs.

Tableau de correspondance des targets systemd

WantedBy= est le plus courant, mais on peut également trouver :

  • RequiredBy= qui permet de spécifier une dépendance recquise au démarrage de l’unité. Si la dépendance n’est pas respecté, l’unité ne démarrera pas
  • Alias= permet d’activer l’unité sous un autre nom
  • Also= permet d’activer/désactiver les unités comme un ensemble
  • DefaultInstance= utilisé comme valeur de repli, concernant les templates d’unité nommant des instances de manière aléatoire

Création de mon propre service

Lancement et management d’un container Nginx avec systemd.

Création du fichier service

$ sudo nano /etc/systemd/system/nginx-docker.service

Contenu du fichier

[Unit]

Description=Container Nginx with systemD
After=docker.service
Requires=docker.service


[Service]

Type=simple
ExecStartPre=-/usr/bin/docker kill systemd_nginx
ExecStartPre=-/usr/bin/docker rm systemd_nginx
ExecStartPre=-/usr/bin/docker pull nginx:latest
Restart=on-success
ExecStart=/usr/bin/docker run -d --name systemd_nginx --restart always -p 8080:80 nginx:latest
ExecStop=/usr/bin/docker stop systemd_nginx
RemainAfterExit=yes


[Install]
WantedBy=multi-user.target

Rechargement de systemd pour la prise en compte de mon nouveau service

$ sudo systemctl daemon-reload

On peut maintenant le manager :

$ systemctl start nginx-docker.service
$ systemctl status nginx-docker.service

● nginx-docker.service - Container Nginx with systemD
 Loaded: loaded (/etc/systemd/system/nginx-docker.service; disabled)
 Active: active (exited) since jeu. 2018-03-22 18:42:18 CET; 5s ago
 Process: 764 ExecStart=/usr/bin/docker run -d --name systemd_nginx --restart always -p 8080:80 nginx:latest (code=exited, status=0/SUCCESS)
 Process: 745 ExecStartPre=/usr/bin/docker pull nginx:latest (code=exited, status=0/SUCCESS)
 Process: 741 ExecStartPre=/usr/bin/docker rm systemd_nginx (code=exited, status=0/SUCCESS)
 Process: 687 ExecStartPre=/usr/bin/docker kill systemd_nginx (code=exited, status=0/SUCCESS)
 Main PID: 764 (code=exited, status=0/SUCCESS)

On s’assure que notre instance Nginx est bien présente :

$ curl --silent localhost:8080 | head -n 5
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

Sources et documentations complémentaires

Je poste ici mes sources, qui m’ont permis la rédaction de ce billet. Il y a également des liens annexes, pour approfondir la compréhension de systemd. Car oui, systemd est très très très très très très …. vaste ! 🙂

LinuxFR – systemd

Getting started with systemd

systemd – ArchWiki

Systemd – Léa Linux

Freedesktop – systemd.service

BONUS

systemd-vs-sysVinit-cheatsheet
Supras

Supras

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *