Como faço para criar um trabalho Upstart de execução única com conclusão garantida antes do início de dois outros trabalhos?

Como faço para criar um trabalho Upstart de execução única com conclusão garantida antes do início de dois outros trabalhos?

Como alguém escreve uma tarefa Upstart com execução garantida?apenas uma vezapós cada inicialização, mas também tem garantia de execução até a conclusão antes de qualquer um dos pelo menos dois outros trabalhos começar a ser executado. Não quero alterar os arquivos init do Upstart para esses dois outros trabalhos, pois eles não pertencem a mim. Reiniciar qualquer um desses dois outros trabalhos não deve fazer com que a tarefa desejada seja executada novamente.

A situação é que a tarefa desejada deve fazer algumas modificações em alguns arquivos do sistema de arquivos local que serão necessários para ambos os outros trabalhos.

Sou completamente novo no Upstart e acho que a curva de aprendizado é mais acentuada do que eu esperava, então uma educação empor quea solução funcionar será tão valiosa quanto a própria solução.

Responder1

Acredito que tenho uma resposta para minha própria pergunta que aproveitaA solução parcial de CameronNemoeA resposta de Mark Russellpara uma questão relacionada, mas um pouco diferente.

São necessários dois arquivos de configuração do Upstart. O primeiro é um trabalho que inicia assim que o sistema de arquivos local está disponível, executa as modificações desejadas no arquivo como um script de pré-inicialização e, em seguida, fica ocioso no estado de execução para sempre:

# modify-files - Single-execution file modification job

start on local-filesystems

console log

pre-start script
  echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB"
  exec /path/to/your/script
end script

O segundo arquivo de configuração é uma tarefa Upstart que atrasa o início de todos os outros trabalhos que possam depender dos arquivos que estamos tentando modificar. Produz uma instância de si mesmo por trabalho dependente:

# modify-files-wait - Helper task for modify-files

start on (starting jobA or jobB)
stop on (started modify-files or stopped modify-files)

instance $JOB

console log
normal exit 0 2
task

script
  echo "$(date --rfc-3339=ns) $(hostname) $UPSTART_JOB ($UPSTART_INSTANCE)"
  status modify-files | grep -q "start/running" && exit 0
  start modify-files || true
  sleep infinity
end script

O Upstart eliminará todas as instâncias que modify-files-waitestiverem modify-filesociosas em seu estado de execução. Essa normal exitlinha explica a possibilidade de ser morto durante seu sono infinito. Precisamos da tasklinha para bloquear jobA e joB até que o estado parado seja alcançado. Qualquer instância executada primeiro será iniciada modify-files, se ainda não tiver sido iniciada.

Como modify-filesnunca atinge seu estado parado, ele nunca será executado novamente, independentemente de o jobA ou o jobB ser reiniciado.

Esta solução parece estar funcionando, mas agradeço quaisquer críticas ou melhorias.

Responder2

Você pode definir um job de tarefa simples que inicia no evento de sua escolha, executa seu script e no final emite evento para iniciar os outros dois jobs.

Por exemplo:

# mainJob - 
#
# This service emit myEvent to run firstJob 
description "emit myEvent to run firstJob"
start on runlevel [2345]
task
console log
script
     echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS" 
     exec /path/to/your/script
     initctl emit -n myEvent
end script

Para não modificar o script inicial dos outros dois trabalhos, você devesubstituir arquivosque permitem modificar a maneira como um trabalho é iniciado e interrompido, modificando as condições de início e parada.

Seguindo meus exemplos criei um simples firstJob.confassim:

# firstJob - 
#
# This service print environment variable 
description "print environment variable"
start on runlevel [2345]
stop on runlevel [016]
task
console log
script
if [ "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" -o "$RUNLEVEL" = "6" ]; then
     exec  echo "(stopTask) $UPSTART_JOB -- $UPSTART_EVENTS"  
else
     exec  echo "(startTask) $UPSTART_JOB -- $UPSTART_EVENTS" 
fi
end script

E então eu substituo start na condição de criar o arquivo de substituição:

echo "start on myEvent" > /etc/init/firstJob.override

Então firstJobcomeçará myEventgerado por mainJobe parará emrunlevel [016]

Testei esses trabalhos no lubuntu 12.04 e após a reinicialização encontrei em /var/log/upstart/firstJob.log:

  (startTask) firstJob -- myEvent

Você deve verificar se "os outros dois trabalhos" precisam de uma condição de evento específica para iniciar e ter certeza de que mainJobiniciam nesses eventos.

Responder3

start on starting jobA or starting jobB

instance $JOB

pre-start exec /path/to/script

O bit inicial impede que os trabalhos prossigam em seu ciclo de vida até que o trabalho seja concluído.

O bit de instância serve para que ambos os eventos iniciais (para jobA e jobB) sejam inibidos, e não apenas um, como seria o caso se você não tivesse uma sub-rotina de instância.

O uso de exec/script pré-inicializado (no lugar de um exec/script regular) é para que quando o script/comando executado terminar, o trabalho ainda será considerado em execução, enquanto com um exec/script tradicional o trabalho é considerado para ser interrompido quando o exec/script sair.

Usar task seria exatamente o que faria o job rodar duas vezes (por exemplo, se os jobs que você tem forem reiniciados), então estamos deixando isso de fora.

informação relacionada