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çãonotify_systemd()
de Pierre-Yves Ritschard ou a funçãonotify_socket()
de Cameron T Norman. - Configurando a unidade de serviço para o serviço com
Type=notify
eNotifyAccess=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
- Jonathan de Boyne Pollard (2015). Problemas de protocolo de prontidão com os daemons do Unix . Respostas frequentemente dadas.
- Lennart Poettering (2010).
sd_notify()
. páginas de manual do systemd. Freedesktop.org. - Lennart Poettering (2010).
systemd-notify
. páginas de manual do systemd. Freedesktop.org. - Como gravar um arquivo de unidade de serviço do systemd para que ele aguarde até que uma interface específica seja ativada antes de iniciar?
- Adicionar informações de status à saída de status do systemd