Je crée un fichier .service systemd et j'ai besoin d'aide pour comprendre la différence entre Requires=
et After=
. La page de manuel indique que Requires=
"Configure les dépendances des exigences sur d'autres unités." et After=
"Configure les dépendances de classement entre les unités." Quelle est la différence?
After=
configure l'ordre de service (ne faites X qu'après Y), tandis que Requires=
dépendances d'état. Si vous ne spécifiez pas de commande, un service dépendant d'un autre serait démarré en même temps que celui dont il dépend. Aussi, la façon 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 instruction serait toujours exécuté si celui nommé dans le After=
la ligne n'est pas démarrée du tout, tandis que Require=
empêcherait son démarrage si l'exigence n'est pas remplie.
Citation https://www.freedesktop.org/software/systemd/man/systemd.unit.html :
Requiert =
Configure les dépendances des exigences sur d'autres unités. Si cette unité est activée, les unités répertoriées ici seront également activées. Si l'une des autres unités est désactivée ou que 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'exigence pour tous les noms répertoriés seront créées. Notez que les dépendances d'exigence n'influencent pas l'ordre dans lequel les services sont démarrés ou arrêtés. Ceci doit être configuré indépendamment avec les options After = ou Before =. Si une unité foo.service nécessite une unité bar.service configurée avec Requiert = et qu'aucune commande n'est configurée avec After = ou Before =, les deux unités seront démarrées simultanément et sans délai entre elles si foo.service est activé. Souvent, c'est un meilleur choix d'utiliser Wants = au lieu de Requirements = afin d'obtenir un système plus robuste face aux services défaillants.
et
Avant =, Après =
Une liste de noms d'unités séparés par des espaces. Configure les dépendances de classement entre les unités. Si une unité foo.service contient un paramètre Before = bar.service et que les deux unités sont démarrées, le démarrage de bar.service est retardé jusqu'au démarrage de foo.service. Notez que ce paramètre est indépendant et orthogonal aux dépendances d'exigence configurées par Requiert =. Il est courant d'inclure un nom d'unité dans les options After = et Requires =, auquel cas l'unité répertoriée sera démarrée avant l'unité configurée avec ces options. Cette option peut être spécifiée plusieurs fois, auquel cas des dépendances de classement pour tous les noms répertoriés sont créées. After = est l'inverse de Before =, c'est-à-dire qu'After = garantit que l'unité configurée est démarrée après le démarrage de l'unité listée, 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 démarre. Notez que lorsque deux unités avec une dépendance d'ordre entre elles sont arrêtées, l'inverse de l'ordre de démarrage est appliqué. c'est-à-dire 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 de commande entre elles, si une unité est arrêtée et l'autre est démarrée, l'arrêt est ordonné avant le démarrage. Peu importe si la dépendance de commande est After = ou Before =. Peu importe également lequel des deux est arrêté, tant que l'un est arrêté et que l'autre est démarré. L'arrêt est ordonné avant le démarrage dans tous les cas. Si deux unités n'ont pas de dépendances de commande entre elles, elles sont arrêtées ou démarrées simultanément et aucune commande n'a lieu.
L'une des principales différences est,
After
vérifie uniquement si l'unité est déjà activée et n'active pas explicitement les unités spécifiées.Requires
sont activées avec l'unité. Si l'une des unités requises ne démarre pas, l'unité n'est pas activée.Considérez que j'ai un fichier d'unité test-app.service
,
[Unit]
Description=test app
After=network-online.target
Voici ce qui se passera lorsque cette instruction sera exécutée,
After
vérifie si network-online.target
.network-online.target
pas démarré, il attendra.test-app
ne démarre qu'après network-online.target
c'est actifSi j'avais à la place Requires
,
[Unit]
Description=test app
Requires=network-online.target
Voici ce qui se passera lorsque cette instruction sera exécutée,
network-online.target
et test-app
sont activés ensemblenetwork-online.target
ne démarre pas test-app
ne sera pas activé.systemd est un gestionnaire de travaux. La page de manuel n'est pas très précise sur la façon dont les choses fonctionnent.
Lorsque vous démarrez, systemd crée une transaction comprenant des travaux pour le travail d'ancrage (c'est-à-dire le travail de démarrage pour default.target). Toutes ces dépendances et relations définissent comment et quels travaux seront déclenchés. La commande définit le ou les travaux sur lesquels chaque autre travail attendra. L'unité default.target est donc au centre de tout cela, c'est pourquoi lorsque vous activez les unités, vous utilisez une dépendance inverse qui, via systemctl enable, crée un lien symbolique du système de fichiers indiquant une dépendance directe que systemd peut suivre (également pourquoi vous avez besoin de liens symboliques de système de fichiers dans le première place). Il en va de même lorsque vous démarrez manuellement une unité, cette unité est l'ancre et la transaction est calculée par rapport à elle.
N'allant pas trop en détail, je vais expliquer ce que requiert = et After =.
Requiert = entraînera systemd pour déclencher un travail de démarrage pour l'unité requise lorsque vous obtenez un travail de démarrage déclenché (explicitement ou via une dépendance: il n'y a aucune distinction en interne). Il a également la propriété de déclencher un travail d'arrêt sur vous lorsque cette unité est arrêtée (remarque: arrêtée, ne descend pas d'elle-même) ou redémarrée. Cela signifie que si une dépendance/systemctl provoque son arrêt/redémarrage, vous arrêterez/redémarrerez également. Cependant, s'il tombe de lui-même, vous ne vous arrêterez pas, car il n'y avait pas de travail, et le changement d'état s'est produit sans l'implication de systemd. C'est là que vous utiliseriez BindsTo = (similaire aux unités de périphérique, qui peuvent devenir inactives sans l'implication de systemd, pour des raisons évidentes).
Maintenant, l'utilisation d'After = est recommandée, car Requiert = seul est efficace pour ce qu'il fait: annulez l'exigence si le travail de démarrage échoue. Cette annulation ne fonctionne cependant que pour les travaux, c.-à-d. Si l'autre unité ne définit pas l'ordre, systemd se déclenche en parallèle, et si son travail de démarrage se termine avant l'échec de votre travail de démarrage, il ne sera pas annulé (il ne peut pas être annulé, en fait) . L'utilisation de After = signifie que l'autre travail continue d'attendre jusqu'à ce que le travail de démarrage de l'unité requise se termine, et selon le résultat, s'il échoue, le travail de démarrage en attente de votre unité est annulé avec le résultat du travail JOB_DEPENDENCY (pourquoi vous utilisez du jaune [DEPEND] au démarrage pour de tels cas). Par conséquent, cet effet d'invalidation n'est pas déterministe sans l'utilisation de After =.
C'est pourquoi utiliser Wants = sans After = est bien si vous ne voulez pas attendre le démarrage de l'autre unité: comme il n'y a pas d'invalidation là-bas, il n'y a donc pas de race. Dans ce cas, il ne s'agit que d'un mécanisme de synchronisation.
En outre, vous pouvez également activer les deux au démarrage, et ne pas exiger les uns des autres, et définir uniquement l'ordre, dans ce cas, lorsque les deux sont extraits dans le cadre de la même transaction, ils seront commandés (ou si le travail de l'autre est déclenché pendant que le travail de l'unité sur laquelle il veut s'exécuter est en cours d'exécution, il attend d'abord qu'il se termine, entre les transactions).
Maintenant, s'il n'y a pas de travail, 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 Requiert = et Veut =, ou les deux sont interceptés à la fois et définissent un ordre, auquel cas ils attendent le travail de l'autre unité.