Como um sinalizador de serviço systemd está pronto, para que outros serviços possam esperar que ele esteja pronto antes de iniciar?

5

Eu tenho um monte de serviços (digamos C0 , C1 ,… C9 ) que só devem começar depois que um serviço S tiver concluído sua inicialização e estiver totalmente em execução e pronto para os outros serviços. Como faço para organizar isso com o systemd?

Em Solicitando serviços com ativação de caminho e destino no systemd , assume-se que o serviço S tem um mecanismo para escrevendo algum tipo de arquivo de bandeira. Suponha aqui, em contraste, que eu tenho controle total sobre o programa que o serviço S executa, e pode adicionar mecanismos systemd nele, se necessário.

    
por JdeBP 20.12.2016 / 17:38

3 respostas

5

Um não precisa necessariamente disso.

Se os serviços C precisarem esperar que S esteja pronto para que possam abrir uma conexão de soquete, então não é necessário fazer isso. Em vez disso, pode-se aproveitar a abertura inicial do soquete de escuta pelos gerentes de serviço.

Vários sistemas, incluindo s6 de Laurent Bercot , my nosh tools , e systemd, tem maneiras em que um socket de escuta pode ser aberto desde cedo, a primeira coisa na configuração do serviço. Todos eles envolvem algo diferente do programa de serviço que abre o soquete de escuta e o programa de serviço, quando invocado, recebendo o (s) soquete (s) de escuta como descritores de arquivo já abertos.

Com o systemd, especificamente, cria-se uma unidade de soquete que define o soquete de escuta. O systemd abre a unidade de soquete e a configura para que o subsistema de rede do kernel esteja atento a conexões; e passa para o serviço real como um descritor de arquivo aberto quando se trata de gerar o (s) processo (s) que manipula (m) conexões para o soquete. (Isso pode ser feito de duas maneiras, assim como inetd poderia, mas a discussão dos detalhes de Accept=true versus Accept=false services está além do escopo dessa resposta.)

O ponto importante é que não é necessário mais ordenação do que isso. O kernel agrupa as conexões do cliente em uma fila até que o programa de serviço seja inicializado e pronto para aceitá-las e conversar com os clientes.

Quando um faz, protocolos de prontidão são a coisa.

O systemd possui um conjunto de protocolos de prontidão que compreende serviço especificado por serviço com a configuração Type= na unidade de serviço. O protocolo de prontidão especial de interesse aqui é o protocolo de prontidão notify . Com ele, o systemd é informado para esperar mensagens do serviço e, quando o serviço está pronto, envia uma mensagem que sinaliza prontidão. O systemd atrasa a ativação dos outros serviços até que a prontidão seja sinalizada.

Usar isso envolve duas coisas:

  • Modificando o código de S de forma que ele chame algo como a função notify_systemd() de Pierre-Yves Ritschard ou a função notify_socket() de Cameron T Norman.
  • Configurando a unidade de serviço para o serviço com Type=notify e NotifyAccess=main .

A restrição NotifyAccess=main (que é o padrão) é porque o systemd precisa saber para ignorar mensagens de programas maliciosos (ou simplesmente defeituosos), porque qualquer processo no sistema pode enviar mensagens para o soquete de notificação do systemd.

Um usa o código de preferência de Pierre-Yves Ritschard ou Cameron T Norman porque não exclui a possibilidade de ter este mecanismo no UbuntuBSD, no Debian FreeBSD, no FreeBSD, no TrueOS, no OpenBSD e assim por diante; que o código fornecido pelos autores do sistema exclui.

Um trap para evitar é o programa systemd-notify . Ele tem vários problemas importantes, não menos do que é que as mensagens enviadas com ele podem acabar sendo jogadas fora do processado pelo systemd. O problema mais importante neste caso é que ele não é executado como o processo "principal" do serviço, portanto, é necessário abrir as notificações de prontidão do serviço S para cada processo no sistema com NotifyAccess=all .

Outra armadilha a ser evitada é pensar que o protocolo forking é mais simples. Não é. Fazê-lo corretamente envolve não bifurcar e sair do pai até que (por um lado) todos os threads de trabalho do programa estejam em execução. Isso não combina como a esmagadora maioria dos daemons que o garfo realmente bifurca.

Leitura adicional

por 20.12.2016 / 17:38

Tags