Como garantir que um trabalho inicial seja iniciado antes de outros trabalhos iniciados?

33

Esta é uma pergunta geral do iniciante, mas deixe-me usar um caso específico:

O Centrify é um gateway do NIS para o ActiveDirectory. Ele precisa carregar antes de qualquer serviço que dependa do serviço de autenticação que ele fornece, por exemplo, autofs, cron, nis, et al.

Isso provou ser bastante desafiador, mesmo ao tentar alterar as dependências dos outros serviços (o que eu acho que não deveríamos fazer de qualquer maneira, não quero tocar nos outros trabalhos do Upstart, se possível) .

Sugestões?

Mark Russell
fonte

Respostas:

29

A solução é abordar o problema de outra direção: para satisfazer os critérios de inicialização do Centrify, não é necessário fazer com que os serviços existentes dependam do novo serviço do Centrify, mas fazer com que o novo serviço do Centrify dependa dos serviços existentes.

Por exemplo, um arquivo de configuração Upstart /etc/init/centrify.confpode dizer:

iniciar (iniciando cron ou iniciando autofs ou iniciando nis)

Convertendo isso para o inglês, isso seria traduzido como:

inicie o serviço Centrify imediatamente antes do início do cron, autofs ou nis (o que ocorrer primeiro).

A ordem na qual o cron, autofs ou nis é iniciado é irrelevante: O Upstart garantirá que o Centrify seja iniciado antes do início do serviço, garantindo assim que o Centrify esteja em execução antes do início de qualquer um desses serviços.

Observe também que o Upstart bloqueará o início do primeiro serviço que deseja iniciar até que o Centrify comece a ser executado.

Muito elegante e simples quando você se acostuma a pensar dessa maneira.

James Hunt
fonte
4
isso parece totalmente ao contrário para mim. por que o script conf para um serviço deve ser modificado quando outras coisas dependem dele ?
ben w
3
@ benw Para que você não precise modificar as configurações existentes dos serviços que não possui.
Paccc 31/07
1
@ Paccc quando eu escrevo um novo script que depende do nginx, eu tenho que modificar o script conf para o nginx ... que eu não possuo.
ben w
2
@ Benw Por que você não pode usar start on (started nginx)em seu novo script?
Paccc 31/07
2
@ Pacc não realmente. start on (started nginx)significa "iniciar meu serviço após o nginx". O que não é o mesmo que "iniciar o nginx antes do meu serviço porque ele precisa".
sickill
12

A resposta de James funciona para uma dependência de 1 para 1. Para 1 a muitos, ou seja, para garantir que o serviço A seja iniciado antes dos serviços B, C e D, você precisa adotar outra abordagem. Você pode consultar os scripts atuais do portmap, mas aqui está a abordagem geral: crie um script de espera.

Cenário: você deseja que seu Serviço A seja executado sempre antes do serviço-b, serviço-c e serviço-d.

Solução: crie um script de espera para o Serviço A. Chame-o de "/etc/init/service-a-wait.conf"

# service-a-wait

start on (starting service-b 
    or starting service-c
    or starting service-d)
stop on (started service-a or stopped service-a)

# We know that we have more than one job that needs to wait for service-a and
# will make use of this service, so we need to instantiate.
instance $JOB

# Needed to make starting the job successful despite being killed
normal exit 2
task

script

    status service-a | grep -q "start/running" && exit 0
    start service-a || true

    # Waiting forever is ok.. upstart will kill this job when
    # the service-a we tried to start above either starts or stops
    while sleep 3600 ; do :; done

end script

O que isso significa em inglês simples é: quando o serviço b, c ou d sinalizar que deseja iniciar, eles devem esperar para iniciar até que o serviço-a esteja em execução. O trabalho de serviço em espera foi projetado para ser executado até que o serviço a seja iniciado. Depois que o serviço em espera termina, agora os serviços b, c e d ficam livres para continuar e executar.

Isso garantirá que o serviço-a esteja em funcionamento antes que qualquer uma de suas dependências reversas tente iniciar.

Nota: a linha "instance $ JOB" é importante neste cenário "iniciar em ... ou .. ou ..". Caso contrário, você realmente bloqueará apenas o que ocorrer com B, C ou D primeiro.

(a instanciação merece uma explicação melhor honestamente. por enquanto, basta fazê-lo.;)

Mark Russell
fonte
3
Eu não entendo isso ... o que impede uma condição de corrida entre o início do serviço A e o serviço B continuando? Eu não vejo como iniciante vai saber que o script tenha completado "iniciar o serviço-a" ... (culpo isso em documentação de má qualidade do Upstart talvez ...)
Chris Pacejo
@ Mark Russell: Essa normal exit 2linha não deveria ser normal exit 0 2? A primeira linha da scriptseção pode claramente exit 0.
froage