efeito do sinal de reinicialização no estado do serviço systemd

1

Estou trabalhando com systemd services no momento. Qual é a seqüência de mudanças de estado que todos os serviços executam quando, por exemplo, init 6 ou reboot ou init 0 são executados?

Aqui está o cenário que gerou essa pergunta:

Eu tenho um serviço A que deve ser ativado em desligamentos e reinicializações. Destina-se a chamar recuperar informações de outro serviço, serviço B . B deve ser ativado na inicialização e ser executado continuamente.

Quando reboot ou init 0 são executados, em que estado pode A esperar encontrar B ?

Eu achei este parágrafo sobre o tópico interessante, mas não entrou em detalhes suficientes.

ActiveState contains a state value that reflects whether the unit is currently active or not. The following states are currently defined: active, reloading, inactive, failed, activating, deactivating. active indicates that unit is active (obviously...). reloading indicates that the unit is active and currently reloading its configuration. inactive indicates that it is inactive and the previous run was successful or no previous run has taken place yet. failed indicates that it is inactive and the previous run was not successful (more information about the reason for this is available on the unit type specific interfaces, for example for services in the Resultproperty, see below). activating indicates that the unit has previously been inactive but is currently in the process of entering an active state. Conversely deactivating indicates that the unit is currently in the process of deactivation.

link

    
por scottyseus 24.06.2015 / 21:23

1 resposta

7

Nas configurações do systemd, reboot , poweroff , halt e init N todos são convertidos em vários subcomandos de systemctl . Eu falarei em termos de systemctl a partir de agora.

Então, o que acontece quando você emite (por exemplo) um comando systemctl reboot ? Exceto o camada de abstração polkit / logind (que, de qualquer forma, não é usada quando privilégios de root estão disponíveis), este comando se traduz em systemctl isolate reboot.target , que por sua vez é equivalente a systemctl start --job-mode=isolate reboot.target .

Na linguagem systemd, para "isolar" uma unidade (seja um alvo, um serviço ou qualquer outra coisa) significa iniciar (ativar) uma determinada unidade junto com todas as suas dependências E parar (desativar) todas as outras unidades, a menos que tenham IgnoreOnIsolate=yes especificado . Portanto, quando você emite um comando de reinicialização, reboot.target (com suas dependências) é enfileirado para iniciar e todas as outras unidades são enfileiradas para parar.

Não examinaremos as dependências desses destinos manualmente (embora seja possível com o comando systemctl list-dependencies ). Vamos, em vez disso, olhar para bootup (7) , uma página man descrevendo o que acontece na inicialização / desligamento de um sistema controlado pelo sistema.

O gráfico ASCII correspondente é copiado e colado aqui (FTR, reflete systemd 221).

                              (conflicts with  (conflicts with
                                all system     all file system
                                 services)     mounts, swaps,
                                     |           cryptsetup
                                     |          devices, ...)
                                     |                |
                                     v                v
                              shutdown.target    umount.target
                                     |                |
                                     \_______   ______/
                                             \ /
                                              v
                                     (various low-level
                                          services)
                                              |
                                              v
                                        final.target
                                              |
        _____________________________________/ \_________________________________
       /                         |                        |                      \
       |                         |                        |                      |
       v                         v                        v                      v
systemd-reboot.service   systemd-poweroff.service   systemd-halt.service   systemd-kexec.service
       |                         |                        |                      |
       v                         v                        v                      v
reboot.target             poweroff.target            halt.target           kexec.target

O esquema é bastante autoexplicativo. A meta especial shutdown.target por padrão entra em conflito com todas as unidades de serviço (a menos que tenham DefaultDependencies=no definido).

Portanto, a primeira abordagem seria tornar sua A service uma dependência de shutdown.target , para que ela seja ativada em todos os desligamentos. (Observe que isso também exigirá que seja DefaultDependencies=no .)

No entanto, por padrão, tudo no systemd é feito em paralelo, portanto, o A service também precisa ser solicitado em relação a B - para atrasar o desligamento de B até que A inicie e conclua sua recuperação de dados. Em systemd.unit (5) , podemos ler:

If one unit with an ordering dependency on another unit is shut down while the latter is started up, the shut down is ordered before the start-up regardless of whether the ordering dependency is actually of type After= or Before=.

Isso é lamentável: independentemente de fazermos A After=B.service ou Before=B.service , B será interrompido antes de A ser iniciado.

Então, devemos ir por outro caminho. Podemos criar um serviço normal de Type=oneshot , que não faz nada ( /bin/true ) na ativação, mas faz o que for necessário na desativação. (Isso também exigirá que ele seja RemainsAfterExit=yes ou o serviço será automaticamente marcado como inativo assim que /bin/true sair.) Esse serviço pode ser solicitado em relação a B.service conforme necessário:

Note that when two units with an ordering dependency between them are shut down, the inverse of the start-up order is applied. i.e. if a unit is configured with After= on another unit, the former is stopped before the latter if both are shut down.

Juntando tudo isso, um arquivo de unidade para A.service será parecido com isto:

[Unit]
Description=Collect information about B

# we want to deactivate together with B
Requisite=B.service

# we want to deactivate before B deactivates
After=B.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecStop=/path/to/B

[Install]
# replace with whatever is needed
WantedBy=B.service

Observe também que se uma versão recente (≥ 217) do systemd for usada, então ExecStart=/bin/true pode ser completamente deixado de fora .

Leitura adicional

  1. página de manual do systemd (1) , seção "Conceitos".
  2. Página de manual systemd.unit (5) , seção "Opções da Seção [Unidade]".
  3. Página de manual de inicialização (7) .
  4. Página de manual systemd.special (5) .
por 29.06.2015 / 16:52