Comprendre les cibles systemd : concepts essentiels expliqués
Comprenez les cibles systemd, les cibles de démarrage par défaut, les correspondances de niveaux d'exécution, l'isolation, les cibles personnalisées et les commandes de dépannage.
Comprendre les cibles systemd : concepts essentiels expliqués
Les cibles systemd sont plus faciles à comprendre si vous arrêtez de les considérer comme des services. Un service démarre un processus. Une cible regroupe des unités dans un état système nommé. Lorsqu'une machine démarre sur multi-user.target, systemd ne démarre pas un programme appelé "multi-user". Il essaie d'atteindre un état où les unités souhaitées par cette cible ont été démarrées ou au moins ont eu leurs tentatives de démarrage effectuées.
Cette distinction aide lorsque vous déboguez des problèmes de démarrage. Si graphical.target est lent, la cible elle-même est rarement le problème. L'une des unités d'affichage, de connexion, de réseau, de montage ou d'application intégrée à cette cible est lente ou défaillante. Les cibles vous donnent la carte.
Que sont les cibles systemd ?
Dans l'écosystème systemd, une cible est un type spécial de fichier d'unité (comme les fichiers .service ou .socket) qui sert un objectif organisationnel critique. Contrairement aux unités de service qui définissent comment démarrer ou arrêter un processus spécifique, les unités cibles définissent un état système ou une collection d'unités qui doivent être actives ensemble. Elles agissent comme des points de regroupement logiques et des points de synchronisation pour d'autres unités systemd.
Considérez les cibles comme des jalons dans le parcours opérationnel du système. Lorsque systemd démarre, il ne lance pas simplement une liste de services de manière arbitraire ; il travaille pour atteindre une cible spécifique. Cette cible, à son tour, intègre tous les services, sockets, points de montage et autres cibles nécessaires pour que cet état soit atteint. Cette approche basée sur les dépendances garantit un processus de démarrage prévisible et efficace.
Pour ceux qui connaissent les anciens systèmes d'initialisation Linux comme SysVinit, les cibles systemd sont l'équivalent moderne des niveaux d'exécution. Alors que SysVinit avait un ensemble fixe de niveaux d'exécution (par exemple, le niveau d'exécution 3 pour le mode texte multi-utilisateur, le niveau d'exécution 5 pour le mode graphique multi-utilisateur), les cibles systemd sont plus flexibles. Elles sont nommées, non numérotées, et vous pouvez définir des cibles personnalisées, offrant une plus grande granularité et extensibilité.
Comment fonctionnent les cibles : regroupement et dépendances
Les cibles réalisent leurs capacités de regroupement et de définition d'état grâce à des dépendances explicites définies dans leurs fichiers d'unité. Les directives principales utilisées pour cela sont Wants=, Requires=, After= et Before=.
Wants=: Spécifie des dépendances "faibles". Sicible AWants=unité B, systemd essaiera de démarrerunité Blorsquecible Aest activée. Cependant,cible Adémarrera même siunité Béchoue à démarrer. Ceci est couramment utilisé pour regrouper des services connexes qui sont souhaitables mais pas strictement essentiels.Requires=: Spécifie des dépendances "fortes". Sicible ARequires=unité B, alorsunité Bdoit être démarrée avec succès pour quecible As'active. Siunité Béchoue,cible Aéchouera également ou ne démarrera pas. Ceci est utilisé pour les dépendances critiques.After=: Définit une dépendance d'ordonnancement. Sicible AaAfter=unité B, alorscible Ane démarrera qu'après queunité Ba démarré. Cela n'implique pas une dépendance de succès, seulement un ordre.Before=: L'inverse deAfter=. Sicible AaBefore=unité B, alorsunité Bne démarrera qu'après quecible Aa démarré.Conflicts=: Garantit que certaines unités ne sont pas actives simultanément. Sicible AConflicts=unité B, alors l'activation decible Aarrêteraunité Bsi elle est en cours d'exécution, et vice-versa.
Ces directives permettent aux cibles d'agir comme des orchestrateurs robustes, intégrant des services et d'autres cibles selon les besoins, et définissant l'ordre dans lequel ils doivent démarrer. Par exemple, multi-user.target Wants= typiquement network.target et divers autres services, garantissant qu'ils sont actifs lorsque le système atteint un état multi-utilisateur.
Vous pouvez inspecter le contenu d'un fichier d'unité cible pour voir ses dépendances :
systemctl cat multi-user.target
Cette commande affichera le contenu du fichier d'unité multi-user.target, montrant sa Description, sa Documentation, et surtout, ses directives Wants=, Requires=, After= et autres qui définissent ce qui constitue l'état multi-utilisateur.
Cibles systemd courantes expliquées
Systemd fournit une variété de cibles prédéfinies, chacune correspondant à un état système ou une fonctionnalité spécifique. Comprendre celles-ci est crucial pour l'administration système :
default.target: C'est la cible la plus importante car elle définit l'état par défaut dans lequel votre système démarrera. C'est généralement un lien symbolique versgraphical.target(pour les ordinateurs de bureau) oumulti-user.target(pour les serveurs).graphical.target: Cette cible est typiquement utilisée pour les systèmes avec un environnement de bureau graphique. Elle intègremulti-user.targetpuis ajoute les services nécessaires au gestionnaire de connexion graphique et au serveur d'affichage (par exemple, GDM, LightDM, Xorg, Wayland).multi-user.target: C'est l'état standard pour les systèmes multi-utilisateurs sans interface graphique. C'est courant pour les serveurs et fournit tous les services nécessaires à l'accès en ligne de commande, au réseau et à la plupart des opérations de démon.basic.target: Un état minimal qui inclut les services système de base nécessaires aux opérations fondamentales, mais avantmulti-user.target. Il intègre typiquementsysinit.targetet d'autres services essentiels.sysinit.target: Cette cible est atteinte très tôt dans le processus de démarrage. Elle est responsable des tâches d'initialisation centrales du système comme le montage des systèmes de fichiers/etc/fstab(à l'exception des systèmes distants), la configuration du swap et d'autres initialisations liées au matériel.local-fs.target: Garantit que tous les systèmes de fichiers locaux spécifiés dans/etc/fstabsont montés.remote-fs.target: Garantit que tous les systèmes de fichiers distants (par exemple, NFS, CIFS) spécifiés dans/etc/fstabsont montés.network.target: Indique qu'une connectivité réseau de base est disponible (par exemple, les interfaces réseau sont actives). Cela ne garantit pas une connectivité Internet complète ou une attribution d'adresse IP.network-online.target: Un point de synchronisation pour les services qui veulent attendre que le gestionnaire de réseau considère le réseau en ligne. Cela ne prouve pas qu'Internet, le DNS ou une API distante est accessible, et cela ne fonctionne comme prévu que lorsque le service wait-online correspondant est activé.rescue.target: Fournit un shell mono-utilisateur avec des services minimaux en cours d'exécution et les systèmes de fichiers locaux montés. Utile pour la récupération du système et le dépannage.emergency.target: Un environnement encore plus minimal querescue.target. Il fournit un shell sur le système de fichiers racine, qui est généralement monté en lecture seule. Aucun autre service n'est démarré. Pour les situations d'urgence critiques.poweroff.target,reboot.target,halt.target: Ces cibles sont utilisées pour éteindre, redémarrer ou arrêter le système, respectivement. Lorsqu'elles sont activées, elles arrêtent la plupart des services et préparent le système à l'état d'alimentation souhaité.
Gestion des cibles systemd
L'interaction avec les cibles systemd implique principalement l'utilitaire en ligne de commande systemctl.
Affichage des cibles actives et par défaut
Pour voir dans quelle cible votre système fonctionne actuellement :
systemctl get-default
Pour lister toutes les unités cibles actuellement chargées :
systemctl list-units --type=target
Cette commande montre les cibles actives, chargées et statiques, ainsi que leurs descriptions.
Modification de la cible de démarrage par défaut
Vous pouvez modifier la cible dans laquelle votre système démarre par défaut. Par exemple, pour définir multi-user.target comme cible par défaut :
sudo systemctl set-default multi-user.target
Pour revenir à graphical.target :
sudo systemctl set-default graphical.target
Cette commande crée un lien symbolique de /etc/systemd/system/default.target vers le fichier cible souhaité.
Démarrage temporaire dans une cible différente
Parfois, vous devez démarrer dans une cible spécifique une seule fois (par exemple, pour le dépannage). Vous pouvez y parvenir en ajoutant un paramètre de noyau lors du démarrage. Lorsque le menu de démarrage GRUB apparaît, modifiez l'entrée de démarrage (généralement en appuyant sur e) et ajoutez systemd.unit=nom_cible.target à la ligne de commande du noyau.
Par exemple, pour démarrer en mode rescue :
systemd.unit=rescue.target
Changement de cible pendant l'exécution
Vous pouvez passer à une cible différente pendant que le système est en cours d'exécution en utilisant la commande systemctl isolate. Cette commande arrêtera tous les services non requis par la nouvelle cible et démarrera tous les services requis par celle-ci.
Avertissement : L'utilisation de systemctl isolate peut perturber le fonctionnement de votre système, surtout si vous passez à une cible de niveau beaucoup plus bas comme multi-user.target depuis graphical.target sur une machine de bureau. Utilisez avec précaution.
Pour passer de graphical.target à multi-user.target :
sudo systemctl isolate multi-user.target
Pour revenir à graphical.target (en supposant que c'était l'état précédent) :
sudo systemctl isolate graphical.target
Création de cibles personnalisées
Bien que systemd fournisse de nombreuses cibles utiles, vous pourriez trouver des situations où la création d'une cible personnalisée est bénéfique. C'est particulièrement vrai pour les déploiements d'applications complexes où vous devez regrouper plusieurs services qui doivent toujours démarrer et s'arrêter ensemble, ou pour définir un environnement spécifique pour votre application.
Pour créer une cible personnalisée :
- Créez un fichier
.target: Placez-le dans/etc/systemd/system/. Par exemple,my-application.target.# /etc/systemd/system/my-application.target [Unit] Description=Ma cible d'application personnalisée Wants=my-database.service my-webserver.service After=my-database.service my-webserver.serviceDescription: Une description lisible par l'humain.Wants=: Listez les services ou autres cibles que cette cible doit intégrer.After=: Définissez l'ordre. La cible démarrera après ces unités.
- Créez les services : Assurez-vous que
my-database.serviceetmy-webserver.service(ou quels que soient les services que vous listez) existent et sont correctement configurés. - Rechargez systemd : Informez systemd du nouveau fichier d'unité.
sudo systemctl daemon-reload
4. **Activez et démarrez** : Vous pouvez maintenant activer et démarrer votre cible personnalisée, ce qui démarrera à son tour ses services souhaités. bash
sudo systemctl enable my-application.target
sudo systemctl start my-application.target
```
Cela vous permet de gérer un groupe de services connexes comme une seule unité logique, simplifiant les déploiements d'applications complexes.
Niveaux d'exécution et cibles sans détours
Si vous venez de SysVinit, la correspondance approximative est :
| Ancienne idée de niveau d'exécution | Cible systemd courante |
|---|---|
| Mode de réparation mono-utilisateur | rescue.target |
| Mode texte multi-utilisateur | multi-user.target |
| Mode graphique multi-utilisateur | graphical.target |
| Redémarrage | reboot.target |
| Extinction | poweroff.target |
Considérez cela comme une aide à la traduction, pas un modèle parfait. Les niveaux d'exécution SysV étaient un petit ensemble fixe d'états numérotés. Les cibles systemd sont des unités nommées avec des dépendances, et il peut y en avoir beaucoup. Un paquet peut installer sa propre cible. Vous pouvez en créer une pour un flux de travail de déploiement. Certaines cibles sont destinées à être isolées ; d'autres ne sont que des points de regroupement utilisés lors du démarrage.
Vous pouvez voir quelles cibles permettent l'isolation avec :
systemctl show multi-user.target -p AllowIsolate
systemctl show basic.target -p AllowIsolate
Cela compte car systemctl isolate n'est pas une commande inoffensive "changer de vue". Elle arrête les unités qui ne font pas partie de la nouvelle transaction de cible. Sur un bureau, isoler multi-user.target arrêtera généralement la session graphique. Sur un serveur distant, isoler la mauvaise cible peut arrêter les services réseau ou de connexion et vous bloquer.
Comment les services deviennent partie d'une cible
La plupart des appartenances quotidiennes à une cible proviennent de la section [Install] d'un fichier de service :
[Install]
WantedBy=multi-user.target
Lorsque vous exécutez :
sudo systemctl enable myapp.service
systemd crée un lien symbolique sous un répertoire tel que :
/etc/systemd/system/multi-user.target.wants/myapp.service
Ce lien symbolique est ce qui fait que multi-user.target souhaite le service lors du démarrage. Le fichier de service peut exister et être parfaitement valide sans être activé. Dans ce cas, démarrer multi-user.target ne l'intégrera pas automatiquement.
C'est pourquoi systemctl start myapp.service et systemctl enable myapp.service résolvent des problèmes différents. start l'exécute maintenant. enable le câble dans une cible de démarrage future. enable --now fait les deux.
Pour vérifier si un service est activé pour une cible :
systemctl is-enabled myapp.service
systemctl list-dependencies multi-user.target | grep myapp
Si un service démarre manuellement mais pas au démarrage, c'est l'une des premières choses à vérifier.
Une petite cible personnalisée qui est réellement utile
Les cibles personnalisées sont plus utiles lorsqu'elles donnent aux opérateurs une seule commande pour un groupe d'unités connexes. Imaginez une pile d'application simple :
app-api.service
app-worker.service
app-scheduler.service
Vous pouvez créer :
# /etc/systemd/system/app-stack.target
[Unit]
Description=Pile d'application
Wants=app-api.service app-worker.service app-scheduler.service
After=network-online.target
Wants=network-online.target
AllowIsolate=no
Ensuite, ajoutez chaque service à la cible :
[Install]
WantedBy=app-stack.target
Après daemon-reload, activez les services ou la cible selon le comportement souhaité :
sudo systemctl daemon-reload
sudo systemctl enable app-api.service app-worker.service app-scheduler.service
sudo systemctl start app-stack.target
Cela vous donne un regroupement lisible sans prétendre que la cible est un superviseur de processus. Si app-worker.service échoue, inspectez ce service. La cible n'est que le point de regroupement.
Si vous voulez que l'arrêt de la cible arrête tous les services de la pile, ajoutez PartOf=app-stack.target à chaque service :
[Unit]
PartOf=app-stack.target
Maintenant, systemctl stop app-stack.target se propage aux services membres. C'est souvent la pièce manquante dans les exemples de cibles personnalisées.
Dépannage avec les cibles
Les cibles sont également inestimables pour le dépannage des problèmes de démarrage ou des échecs de service :
- Identification des dépendances : Si un service ne démarre pas, inspecter la cible à laquelle il appartient peut révéler des dépendances manquantes ou défaillantes. Utilisez
systemctl status <nom_service>etsystemctl list-dependencies <nom_cible>. - Démarrage dans des cibles minimales : Si votre système ne parvient pas à démarrer dans
graphical.targetoumulti-user.target, essayez de démarrer dansrescue.targetouemergency.targeten utilisant la méthode du paramètre de noyau. Cela fournit un environnement minimal où vous pouvez diagnostiquer les problèmes sans la complexité de nombreux services en cours d'exécution. - Vérifiez les journaux : Après avoir tenté de démarrer une cible ou un service, vérifiez toujours les journaux
journalctlpour les erreurs :journalctl -b -u <nom_cible_ou_service>
Meilleures pratiques et conseils
- Utilisez
network-online.targetavec précaution : Si votre service a besoin d'une configuration réseau avant le démarrage, combinezAfter=network-online.targetavecWants=network-online.targetet confirmez que l'unité wait-online appropriée est activée. Gardez toujours une logique de nouvelle tentative dans l'application pour les dépendances distantes. - Comprenez l'ordre de démarrage : Familiarisez-vous avec le flux général de
sysinit.targetàbasic.target, puismulti-user.target/graphical.target. Cela aide à déboguer les services qui échouent tôt dans le processus de démarrage. - Soyez prudent avec
default.target: Changerdefault.targetpeut modifier considérablement le comportement de démarrage de votre système. Testez toujours les configurations personnalisées dans un environnement non productif d'abord. - Utilisez
Wants=pour les dépendances non critiques : Pour les services qui sont utiles mais pas strictement nécessaires pour qu'une cible soit considérée comme "opérationnelle", utilisezWants=au lieu deRequires=. Cela empêche un seul échec de service optionnel de se propager et d'empêcher l'activation de toute la cible.
Le modèle mental à retenir
Une cible est un état nommé, pas un démon. default.target décide de la destination de démarrage normale. multi-user.target est l'état serveur habituel. graphical.target ajoute la pile d'affichage. rescue.target et emergency.target sont des outils de réparation. Les cibles personnalisées sont des outils de regroupement lorsqu'elles rendent les opérations plus claires.
Quand quelque chose lié à une cible se casse, évitez de blâmer la cible en premier. Demandez quelle unité a été intégrée, quelle règle d'ordonnancement l'a retardée et quelle dépendance a échoué. systemctl cat, systemctl list-dependencies, systemctl show et journalctl -b répondront généralement à ces questions plus rapidement que la lecture de diagrammes de démarrage génériques.