Como eu crio um job Upstart de execução única garantido para ser concluído antes que outros dois jobs comecem?

5

Como se escreve uma tarefa Upstart que é garantida para executar somente uma vez após cada inicialização, mas também é garantida a execução até a conclusão de pelo menos duas outras tarefas sendo executadas. Eu não quero alterar os arquivos init Upstart para esses dois outros trabalhos, pois eles não pertencem a mim. Reiniciar 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 no sistema de arquivos local que ambos os outros trabalhos precisarão.

Sou completamente novo no Upstart e acho que é uma curva de aprendizado mais íngreme do que eu esperava, então uma educação sobre por que a solução funciona será tão valiosa quanto a própria solução.

    
por froage 07.10.2014 / 11:41

3 respostas

3

Acredito que tenho uma resposta para minha própria pergunta que aproveita a solução parcial CameronNemo e A resposta de Mark Russell a uma questão relacionada, mas um pouco diferente.

Dois arquivos de configuração do Upstart são necessários. O primeiro é um trabalho iniciado assim que o sistema de arquivos local estiver disponível, executa as modificações desejadas do arquivo como um script de pré-inicialização e 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 podem depender dos arquivos que estamos tentando modificar. Ela 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 de modify-files-wait uma vez modify-files está inativo em seu estado de execução. Essa linha normal exit é responsável pela possibilidade de ser morto durante seu sono infinito. Precisamos que a linha task bloqueie jobA e joB até que o estado parado seja atingido. Qualquer instância executada primeiro começará a modify-files , se ainda não tiver sido iniciada.

Como modify-files nunca atinge seu estado parado, ele nunca será executado novamente, independentemente de jobA ou jobB serem reiniciados.

Esta solução parece estar funcionando, mas saúdo críticas ou melhorias.

    
por froage 10.10.2014 / 10:13
2

Você pode definir um trabalho de tarefa simples que comece no evento de sua escolha, execute seu script e, no evento de emissão final, inicie os outros dois trabalhos.

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 upstart das outras duas tarefas, você deve substituir arquivos que permitem modificar a maneira como um trabalho é iniciado e interrompido, modificando o início e o fim das condições.

Seguindo meus exemplos, criei um firstJob.conf simples como este:

# 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 sobrescrevo a condição de criar um arquivo de substituição:

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

Portanto, firstJob começará em myEvent gerado por mainJob e será interrompido em runlevel [016]

Eu testei estas tarefas no lubuntu 12.04 e depois da reinicialização eu 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 começar e se os mainJob começam com esses eventos.

    
por Lety 09.10.2014 / 01:22
1
start on starting jobA or starting jobB

instance $JOB

pre-start exec /path/to/script

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

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

O uso de pré-inicialização exec / script (no lugar de um exec / script regular) é assim quando o script / comando executado termina, a tarefa ainda será considerada em execução, enquanto que com um exec / script tradicional a tarefa é considerado interrompido quando o exec / script sai.

O uso da tarefa seria precisamente o que faz o trabalho ser executado duas vezes (por exemplo, se os trabalhos que você tem são reiniciados), por isso estamos deixando isso de lado.

    
por CameronNemo 08.10.2014 / 03:07