méthodologie générique pour déboguer les cycles de commande dans systemd

23

Je suis au courant du fil suivant et soi-disant une réponse . Sauf qu'une réponse n'est pas une réponse au sens générique. Il indique quel était le problème dans un cas particulier, mais pas en général.

Ma question est: existe-t-il un moyen de déboguer les cycles de commande de manière générique ? Par exemple: existe-t-il une commande qui décrira le cycle et qu'est-ce qui relie une unité à une autre?

Par exemple, je dois suivre journalctl -b(veuillez ignorer la date, mon système n'a pas de RTC avec lequel synchroniser l'heure):

Jan 01 00:00:07 host0 systemd[1]: Found ordering cycle on sysinit.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on local-fs.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on cvol.service/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on basic.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on sockets.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on dbus.socket/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on sysinit.target/start
Jan 01 00:00:07 host0 systemd[1]: Breaking ordering cycle by deleting job local-fs.target/start
Jan 01 00:00:07 host0 systemd[1]: Job local-fs.target/start deleted to break ordering cycle starting with sysinit.target/start

où cvol.service (celui qui a été introduit et qui rompt le cycle) est:

[Unit]
Description=Mount Crypto Volume
After=boot.mount
Before=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/usr/bin/cryptsetup open /dev/*** cvol --key-file /boot/***

[Install]
WantedBy=home.mount
WantedBy=root.mount
WantedBy=usr-local.mount

Selon journalctl, cvol.service veut basic.service, sauf que ce n'est pas le cas, du moins pas évidemment. Existe-t-il une commande qui démontrerait d'où provient ce lien? Et en général, y a-t-il une commande, qui trouverait les cycles et montrerait l'origine de chaque lien dans le cycle?

galets
la source

Réponses:

20

Existe-t-il une commande qui démontrerait d'où provient ce lien?

Le plus proche que vous pouvez faire est d' systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After cvol.serviceafficher les listes de dépendances (effectives) résultantes pour une unité donnée.

Existe-t-il une commande qui trouverait les cycles et montrerait d'où provient chaque lien du cycle?

À ma connaissance, il n'y a pas une telle commande. En fait, systemd n'offre rien pour faciliter le débogage des cycles de commande (soupir).

Selon journalctl, cvol.service veut basic.service, sauf que ce n'est pas le cas, du moins pas évidemment.

Tout d' abord, les dépendances d'exigence ( Wants=, Requires=, BindsTo=etc.) sont indépendants des dépendances de commande ( Before=et After=). Ce que vous voyez ici est un cycle de dépendance de commande , c'est-à-dire qu'il n'a rien à voir avec Wants=etc.

Deuxièmement, il existe un certain nombre de "dépendances par défaut" créées entre les unités de certains types. Ils sont contrôlés par DefaultDependencies=directive dans la [Unit]section (qui est activée par défaut ).

En particulier, à moins que cette directive ne soit explicitement désactivée, toute .serviceunité de type est implicite Requires=basic.targetet After=basic.targetdépendante, ce qui est exactement ce que vous voyez. Ceci est documenté dans systemd.service (5) .

intelfx
la source
La commande que vous avez citée a parfaitement fonctionné et a en effet révélé une dépendance à l'égard de basic.target. C'est dommage que le jeu d'outils pour systemctl soit si manquant, mais bon, c'est un nouveau projet
galets
2
@galets: À en juger par mon expérience, il y a très peu d'exemples d'une telle pénurie ... Peut-être qu'un jour je contournerai l'augmentation de la verbosité du reporter du cycle, en ajoutant des informations utiles au journal. En attendant, en fait, vous pouvez utiliser systemd-analyze verify UNITpour vérifier l'exactitude de l'unité. Dans les coulisses, cette commande crée une instance de systemd virtuelle et essaie de charger UNIT donné comme transaction initiale (comme si c'était le cas default.target). Cela ne révélera aucune nouvelle information (par rapport aux journaux), mais au moins vous n'aurez pas à redémarrer avec l'unité activée pour voir si elle échoue.
intelfx
demande d'amélioration de systemd (RFE): augmentation de la verbosité du reporter de cycle
adrelanos
20

Vous pouvez visualiser le cycle avec les commandes systemd-analyze verify, systemd-analyze dotet l' GraphViz dot outil:

systemd-analyze verify default.target |&
perl -lne 'print $1 if m{Found.*?on\s+([^/]+)}' |
xargs --no-run-if-empty systemd-analyze dot |
dot -Tsvg >cycle.svg

Vous devriez voir quelque chose comme ceci:

entrez la description de l'image ici

Ici vous pouvez voir le cycle: c.service->b.service->a.service->c.service

Color legend: 
    black     = Requires
    dark blue = Requisite
    dark grey = Wants
    red       = Conflicts
    green     = After

Liens:

Evgeny Vereshchagin
la source
systemd-analyze verifyn'existe pas ici sur une installation debian 8.
sjas
@sjas, systemd-analyze verify disponible depuis v216. essayez systemd-verify. Existe-t-il?
Evgeny Vereshchagin
hm, il n'existe pas sur Jessie: anonscm.debian.org/cgit/pkg-systemd/systemd.git/tree/debian/…
Evgeny Vereshchagin
1
systemd-analyze verify default.targetà elle seule fait un travail décent en montrant la boucle ...
Gert van den Berg
0

étape 1: exécutez la commande de vérification pour default.target

systemd-analyze verify default.target

étape 2: observez quel service ou cible mentionné dans le message "systemd Rupture du cycle de commande en supprimant le travail" et affichez sa liste complète des dépendances

systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After <service or target name mentioned in the "breaking cycle" message>

étape 3: examinez les groupes "après" et "avant" à l'intérieur du fichier de service ou cible généralement défini dans

/lib/systemd/system

et trouver les services ou cibles bien connus pour être séquentiels mais qui sont dans l'ordre sortant pour celui-ci.

Exemple:

dbus.service

est généralement marché "après"

multi-user.target

mais "avant"

sockets.target

une telle dépendance peut être facilement observée en appelant

systemctl list-dependencies default.target

cependant si le fichier

/lib/systemd/system/dbus.service

contenir des lignes comme:

Before=multi-user.target

ou

After=sockets.target

ou les deux simultanément, signifie que dbus.service est défini sortant et qu'il provoque un cycle sans fin systemd.

le remède est simple - changer le mot "après" en "avant" et vice-versa si nécessaire.

Oleg Kokorin
la source