Conjunto de serviços systemd que requerem fase de inicialização comum?

1

No systemd, preciso configurar alguns serviços, que dependem de um serviço de "inicialização" comum, que deve ser concluído antes de serem iniciados. Além disso, gostaria de garantir que os serviços de trabalho e o serviço de "inicialização" podem nunca serem executados simultaneamente a qualquer momento :

                                    manual
    BOOT --.                     "restart svc" ---.
           V                                      V
svc-init   |-----|                                |---------|
svc-a            |--------------------------------|         |----- - - -
svc-b            |--------------------------------|         |----- - - -

Eu quero ter certeza de que os serviços estão "ativados" (executados na inicialização do sistema); Além disso, eu gostaria de poder reiniciar a coisa toda manualmente a qualquer momento que eu precisar.

Como posso fazer isso?

Eu tentei uma configuração com campos importantes, como abaixo:

/etc/systemd/system/svc-init.service:

[Service]
Type=oneshot
ExecStart=/opt/svc/init-svc.sh

[Install]
WantedBy=multi-user.target

.../svc-a.service, .../svc-b.service:

[Unit]
Wants=svc-init.service
After=svc-init.service
Conflicts=svc-init.service

[Service]
Restart=always
ExecStart=/opt/svc/svc.sh

[Install]
WantedBy=multi-user.target

Mas quando tento executá-los, não consigo fazer o que quero:

  1. %código%
    • pára corretamente svc-a & svc-b
    • mas não começa svc-a & svc-b novamente após svc-init ser feito
  2. %código%
    • não força o svc-init a ser executado antecipadamente
  3. %código%
    • o efeito parece o mesmo que em (1) acima (isto é, sudo systemctl start svc-init )
  4. %código%
    • não executa o svc-init
    • impressões: sudo systemctl start svc-a

Quais são os encantamentos do sistema mágico para fazer o sistema se comportar como eu preciso? Ou eu deveria estruturar as unidades de maneira diferente?

edit: Por sugestão nos comentários: para esclarecer, o svc-a & svc-b são no meu caso, na verdade, instâncias de um único serviço, e podem precisar ser dinamicamente iniciado / parado (na verdade eles são: sudo systemctl start svc-a svc-b svc-init , ... start svc-init , sudo systemctl start svc-init svc-a svc-b , etc.).

    
por akavel 05.11.2018 / 15:06

2 respostas

1

O Systemd pode ser difícil de avaliar, mas isso parece ser uma boa experiência para tentar:

svc-init.service

[Unit]
[email protected]

Before informa ao systemd que o svc-init precisa ser todo o caminho feito antes que qualquer serviço nomeado seja iniciado. Isso deve fornecer a sua ordem explícita completa.

svc @ .service

[Unit]
After=svc-init.service
BindsTo=svc-init.service

After simula o Before no svc- serviço init, e pode ser mais conveniente para você. Declará-lo em ambos os lugares não é um erro, nem é necessário. Isso apenas torna explícita sua intenção.

BindsTo informa ao systemd que, se o serviço nomeado for interrompido por qualquer motivo, este também é. Usá-lo com uma declaração After ou Before garante que essa interrupção ocorra na ordem correta. Dependendo de suas necessidades, convém usar Requires em vez de BindsTo , pois Requires indica que apenas pare este serviço quando o serviço nomeado for explicitamente interrompido. Se BindsTo for usado, sempre que svc-init for reiniciado, esse serviço também será reiniciado. Qualquer uma delas é uma versão mais strong da Wants lista em seus exemplos.

Configurado assim, quando svc-init iniciar a partir de um estado parado, ele aguardará para acionar qualquer svc instâncias até que svc-init termine a inicialização (Antes / Depois) e só o faça quando svc-init terminar a inicialização com sucesso (BindsTo). Quando isso for feito, todas as instâncias de svc serão iniciadas. Se svc-init receber um comando stop , todas as instâncias de svc serão interrompidas ao mesmo tempo que svc-init (BindsTo). Se svc-init receber um comando restart , o svc-init e todos os serviços dependentes serão parados e iniciados.

Se svc-init se destinar a lançar e sair, você pode precisar de uma declaração SuccessExitStatus= em sua seção Unit para informar ao systemd quais códigos de saída são esperados em uma inicialização bem-sucedida.

    
por 05.11.2018 / 15:52
-1

Assumindo que você não pode se livrar dos scripts e fazer o systemd fazer toda a configuração em si (o que você quase certamente pode, mas quem escreveu os scripts pode não saber como; gritar com o fornecedor / desenvolvedor até que eles aprendam) você deve usar apenas um arquivo de unidade para isso.

Em um único arquivo de unidade, você executará o script de inicialização em um ExecStartPre= opção. A unidade falhará ao iniciar se o programa chamado aqui falhar ao sair com êxito. Por exemplo, em [email protected] :

[Service]
Restart=always
ExecStartPre=/opt/svc/init-svc.sh %I
ExecStart=/opt/svc/svc.sh %I

[Install]
WantedBy=multi-user.target
    
por 05.11.2018 / 16:19

Tags