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-wait
estiverem modify-files
ociosas em seu estado de execução. Essa normal exit
linha explica a possibilidade de ser morto durante seu sono infinito. Precisamos da task
linha 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-files
nunca 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.conf
assim:
# 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 firstJob
começará myEvent
gerado por mainJob
e 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 mainJob
iniciam 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.