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.