Je suis en train de créer un fichier systemd .service et j'ai besoin d'aide pour comprendre la différence entre Requires=
y After=
. Le site page de manuel dit que Requires=
"Configure les dépendances d'exigences sur d'autres unités." et After=
"Configure les dépendances d'ordre entre les unités." Quelle est la différence ?
Réponses
Trop de publicités?After=
configure l'ordre de service (faire X seulement après Y), tandis que Requires=
les dépendances d'état. Si vous ne spécifiez pas d'ordre, un service dépendant d'un autre sera lancé en même temps que celui dont il dépend. Aussi, de la manière dont je le comprends (bien que je ne puisse pas le tester maintenant et que je ne trouve pas de référence), After=
est un "couplage lâche", et un service avec une telle déclaration continuerait à fonctionner si celui qui est nommé dans la balise After=
n'est pas démarrée du tout, tandis que Requires=
empêcherait son démarrage si la condition n'est pas remplie.
Citant https://www.freedesktop.org/software/systemd/man/systemd.unit.html :
Requiert=
Configure les dépendances des exigences avec d'autres unités. Si cette unité est activée, les unités listées ici seront également activées. Si l'une des autres unités est désactivée ou si son activation échoue, cette unité sera désactivée. Cette option peut être spécifiée plusieurs fois ou plusieurs unités séparées par des espaces peuvent être spécifiées dans une option, auquel cas des dépendances d'exigences seront créées pour tous les noms listés. Notez que les dépendances d'exigences n'influencent pas l'ordre dans lequel les services sont démarrés ou arrêtés. Cela doit être configuré indépendamment avec les options After= ou Before=. Si une unité foo.service nécessite une unité bar.service comme configuré avec Requires= et qu'aucun ordre n'est configuré avec After= ou Before=, alors les deux unités seront démarrées simultanément et sans aucun délai entre elles si foo.service est activé. Souvent, il est préférable d'utiliser Wants= au lieu de Requires= afin d'obtenir un système plus robuste en cas de services défaillants.
et
Avant=, Après=
Une liste de noms d'unités séparés par des espaces. Configure l'ordre des dépendances entre les unités. Si une unité foo.service contient un paramètre Before=bar.service et que les deux unités sont en cours de démarrage, le démarrage de bar.service est retardé jusqu'à ce que foo.service soit démarré. Notez que ce paramètre est indépendant et orthogonal aux dépendances d'exigences telles que configurées par Requires=. Il est courant d'inclure un nom d'unité dans les options After= et Requires=, auquel cas l'unité listée sera démarrée avant l'unité qui est configurée avec ces options. Cette option peut être spécifiée plusieurs fois, auquel cas des dépendances de commande pour tous les noms listés sont créées. After= est l'inverse de Before=, c'est-à-dire que si After= garantit que l'unité configurée est démarrée après que l'unité listée a fini de démarrer, Before= garantit l'inverse, c'est-à-dire que l'unité configurée est complètement démarrée avant que l'unité listée ne soit démarrée. Notez que lorsque deux unités ayant une dépendance d'ordre entre elles sont arrêtées, l'inverse de l'ordre de démarrage est appliqué. C'est-à-dire que si une unité est configurée avec After= sur une autre unité, la première est arrêtée avant la seconde si les deux sont arrêtées. Étant donné deux unités avec une dépendance d'ordre quelconque entre elles, si une unité est arrêtée et l'autre démarrée, l'arrêt est ordonné avant le démarrage. Peu importe que la dépendance d'ordre soit After= ou Before=. Peu importe également laquelle des deux unités est arrêtée, du moment que l'une est arrêtée et l'autre démarrée. L'arrêt est ordonné avant le démarrage dans tous les cas. Si deux unités n'ont pas de dépendance d'ordre entre elles, elles sont arrêtées ou démarrées simultanément, et aucun ordre n'est effectué.
L'une des principales différences est,
-
After
vérifie seulement si l'unité est déjà activée, et n'active pas explicitement les unités spécifiées. - Les unités énumérées dans
Requires
sont activés en même temps que l'unité. Si l'une des unités requises ne démarre pas, l'unité n'est pas activée.
Considérons que j'ai un fichier d'unité test-app.service
,
[Unit]
Description=test app
After=network-online.target
Voici ce qui va se passer lorsque cette instruction sera exécutée,
-
After
vérifie sinetwork-online.target
. - si
network-online.target
n'a pas démarré, il attendra. -
test-app
ne commence qu'aprèsnetwork-online.target
est actif
Si j'avais Requires
à la place,
[Unit]
Description=test app
Requires=network-online.target
Voici ce qui va se passer lorsque cette instruction sera exécutée,
-
network-online.target
ytest-app
sont activés ensemble - si
network-online.target
ne parvient pas à démarrertest-app
ne sera pas activé.
Systemd est un gestionnaire de tâches. La page de manuel n'est pas très précise quant à la façon dont les choses fonctionnent.
Lorsque vous démarrez, ce que fait systemd est de construire une transaction comprenant des travaux pour le travail d'ancrage (c'est-à-dire le travail de démarrage pour default.target). Ce que font toutes ces dépendances et relations, c'est définir comment et quels travaux seront déclenchés. L'ordonnancement définit quel(s) travail(s) chaque autre travail attendra. L'unité default.target est donc au centre de tout cela, c'est pourquoi lorsque vous activez des unités, vous utilisez une dépendance inverse qui, à travers systemctl enable, crée un lien symbolique de système de fichiers indiquant une dépendance directe que systemd peut suivre (c'est aussi pourquoi vous avez besoin de liens symboliques de système de fichiers en premier lieu). De même, lorsque vous démarrez manuellement une unité, cette unité est ancrée et la transaction est calculée par rapport à elle.
Sans entrer dans les détails, je vais vous expliquer ce que font Requires= et After=.
Requires= fera en sorte que systemd déclenche un job de démarrage pour l'unité requise lorsque vous obtenez un job de démarrage déclenché (explicitement, ou par le biais d'une dépendance : il n'y a pas de distinction en interne). Il a également la propriété de déclencher un job d'arrêt lorsque cette unité est arrêtée (note : arrêtée, pas en train de s'éteindre toute seule) ou redémarrée. Cela signifie que si une dépendance/un systèmectl provoque l'arrêt/le redémarrage, vous vous arrêterez/redémarrez également. Cependant, s'il s'arrête de lui-même, vous ne vous arrêterez pas, car il n'y a pas eu de travail, et le changement d'état s'est produit sans l'intervention de systemd. C'est là que vous utiliserez BindsTo= (comme pour les unités de périphériques, qui peuvent devenir inactives sans l'intervention de systemd, pour des raisons évidentes).
Maintenant, l'utilisation de After= est recommandée car Requires= seul est racé pour ce qu'il fait : annuler le requiree si le job de démarrage échoue. Cette annulation ne fonctionne cependant que par rapport aux tâches, c'est-à-dire que si l'autre unité ne définit pas de commande, systemd déclenche les deux en parallèle, et si sa tâche de démarrage se termine avant que votre tâche de démarrage n'échoue, elle ne sera pas annulée (elle ne peut pas être annulée, en fait). L'utilisation de After= signifie que l'autre tâche reste en attente jusqu'à ce que la tâche de démarrage de l'unité requise se termine, et selon le résultat, si elle a échoué, la tâche de démarrage de votre unité en attente est annulée avec le résultat de la tâche JOB_DEPENDENCY (c'est pourquoi vous utilisez le jaune [DEPEND] au démarrage pour de tels cas). Par conséquent, cet effet d'invalidation est indéterminé sans l'utilisation de After=.
C'est pourquoi l'utilisation de Wants= sans After= convient si vous ne voulez pas attendre le démarrage de l'autre unité : comme il n'y a pas d'invalidation, il n'y a pas de course. Dans ce cas, ce n'est rien de plus qu'un mécanisme de synchronisation.
De plus, vous pouvez également activer les deux au démarrage, et ne pas exiger l'un ou l'autre, et seulement définir l'ordre, dans ce cas, lorsque les deux sont tirés dans le cadre de la même transaction, ils seront ordonnés (ou si le travail pour l'autre est déclenché alors que le travail pour l'unité qu'il veut exécuter après est en cours d'exécution, il attendra d'abord qu'il se termine, entre les transactions).
Or, s'il n'y a pas d'emploi, la commande n'a aucun effet pour ladite unité. Cependant, il y a généralement un travail, en raison de l'utilisation de dépendances telles que Requires= et Wants=, ou les deux sont tirés en même temps et définissent un certain ordre, auquel cas ils attendent le(s) travail(s) d'une autre unité.