metodologia genérica para depurar ciclos de pedidos no systemd

23

Estou ciente de seguir o tópico e supostamente uma resposta para ele . Exceto que uma resposta não é uma resposta no sentido genérico. Ele diz qual era o problema em um caso específico, mas não em geral.

Minha pergunta é: existe uma maneira de depurar ciclos de pedidos de maneira genérica ? Por exemplo: existe um comando que descreva o ciclo e o que vincula uma unidade a outra?

Por exemplo, tenho o seguinte journalctl -b(desconsidere a data, meu sistema não possui RTC para sincronizar a hora):

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

onde cvol.service (aquele que foi apresentado e que interrompe o ciclo) é:

[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

De acordo com o journalctl, o cvol.service quer o basic.service, exceto que não, pelo menos não obviamente. Existe um comando que demonstraria de onde esse link é derivado? E, em geral, existe um comando que encontre os ciclos e mostre onde cada link do ciclo se origina?

galets
fonte

Respostas:

20

Existe um comando que demonstraria de onde esse link é derivado?

O mais próximo que você pode fazer é systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After cvol.service, o que mostrará as listas de dependências resultantes (efetivas) para uma determinada unidade.

existe um comando que encontre os ciclos e mostre onde cada link no ciclo se origina?

Que eu saiba, não existe esse comando. Na verdade, o systemd não oferece nada para ajudar na depuração de ciclos de pedidos (suspiro).

De acordo com o journalctl, o cvol.service quer o basic.service, exceto que não, pelo menos não obviamente.

Em primeiro lugar, as dependências de exigência ( Wants=, Requires=, BindsTo=etc.) são independentes das dependências de encomenda ( Before=e After=). O que você vê aqui é um ciclo de dependência de pedidos , ou seja, não tem nada a ver com Wants=etc.

Segundo, há várias "dependências padrão" criadas entre unidades de certos tipos. Eles são controlados por DefaultDependencies=diretiva na [Unit]seção (que é ativada por padrão ).

Em particular, a menos que essa diretiva seja explicitamente desabilitada, qualquer .serviceunidade -type fica implícita Requires=basic.targete After=basic.targetdepende, que é exatamente o que você vê. Isso está documentado em systemd.service (5) .

intelfx
fonte
O comando que você citou funcionou perfeitamente e, de fato, revelou dependência do basic.target. É uma pena que o conjunto de ferramentas para systemctl é tão carente, mas tudo bem, é um novo projeto
Galets
2
@ galets: A julgar pela minha experiência, existem muito poucos exemplos dessa escassez ... Talvez um dia eu consiga aumentar a verbosidade do repórter do ciclo, adicionando algumas informações úteis ao log. Enquanto isso, na verdade, você pode usar systemd-analyze verify UNITpara verificar a correção da unidade. Nos bastidores, este comando cria uma instância virtual do systemd e tenta carregar a UNIT especificada como a transação inicial (como se fosse default.target). Isso não revelará nenhuma informação nova (em comparação com os logs), mas pelo menos você não precisará reiniciar com a unidade ativada para ver se ela falhar.
Intelfx
pedido systemd para o realce (RFE): aumentar o detalhe do repórter ciclo
adrelanos
20

Você pode visualizar o ciclo com os comandos systemd-analyze verify, systemd-analyze doteo GraphViz dot ferramenta:

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

Você deve ver algo assim:

insira a descrição da imagem aqui

Aqui você pode ver o ciclo: c.service->b.service->a.service->c.service

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

Ligações:

Evgeny Vereshchagin
fonte
systemd-analyze verifynão existe aqui em uma instalação do debian 8.
S4 #
@sjas, systemd-analyze verify disponível desde v216. tente systemd-verify. Isto existe?
Evgeny Vereshchagin
hm, ele não existe em Jessie: anonscm.debian.org/cgit/pkg-systemd/systemd.git/tree/debian/…
Evgeny Vereshchagin
1
systemd-analyze verify default.targetem sua própria faz um trabalho decente em mostrar o loop ...
van den Berg Gert
0

etapa 1: execute o comando de verificação para default.target

systemd-analyze verify default.target

etapa 2: observe qual serviço ou destino mencionado na mensagem "systemd Quebrando o ciclo de pedidos excluindo trabalho" e exiba sua lista de dependências completa

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

etapa 3: observe os grupos "depois" e "antes" dentro do arquivo de serviço ou destino normalmente definido em

/lib/systemd/system

e encontre os serviços ou destinos conhecidos por serem seqüenciais, mas estão em ordem de saída para este.

exemplo:

dbus.service

é geralmente mercado "depois"

multi-user.target

mas "antes"

sockets.target

essa dependência pode ser facilmente observada chamando-se

systemctl list-dependencies default.target

no entanto, se o arquivo

/lib/systemd/system/dbus.service

contém linhas como:

Before=multi-user.target

ou

After=sockets.target

ou ambos simultaneamente, significa que o dbus.service é definido como de saída e está causando um ciclo interminável do sistema.

a cura é simples - altere a palavra "Depois" para "Antes" e vice-versa, se necessário.

Oleg Kokorin
fonte