Adicione o manual “wait” no script inicial

2

Eu tenho um script como abaixo:

start on stopped hw_boot
script
/usr/bin/python_program
end script

Isso funciona bem. Mas, para otimizar, gostaria de ocultar o atraso das importações de bibliotecas do python lento (atualmente, leva de 5 a 10 segundos). Uma maneira óbvia é iniciar as importações da biblioteca do python mesmo durante o boot do hw.

Então, o que eu quero fazer é algo como abaixo:

start on some_boot_event (this event is earlier than stopped hw_boot)
script
    //import bunch of python libraries that are needed later
    wait for "stopped hw_boot"
    /usr/bin/python_program
end_script

Como podemos escrever uma lógica para esperar por "hw_boot parado" no script upstart?

    
por sh0731 19.08.2017 / 00:51

1 resposta

3

Eu não vou entrar em detalhes e alinhar todos os scripts do Upstart para você já que você já sabe como escrevê-los, mas vou mostrar as partes cruciais.

Da sua pergunta, vou usar

  • some_boot_event como o evento de inicialização "anterior" que deve acionar a inicialização do programa Python e
  • stopped hw_boot como o par que deveria acionar a execução do programa em Python.

É assim que funciona:

  1. Refatore seu programa em Python para incluir um ponto de entrada que pode ser chamado posteriormente em um momento arbitrário de outros módulos. (Idealmente, seu módulo / programa Python já está escrito dessa forma.) Se o programa atualmente executa qualquer tarefa que não seja de inicialização no tempo de carregamento do módulo, i. e. no escopo global, você deve envolvê-los dentro de um método.

    g. se seu módulo atualmente se parece com isso,

    #!shebang
    import foo, bar
    # ... various constant, class and method definitions ...
    print("Hello World")
    

    você deve refatorar para isso:

    #!shebang
    import foo, bar
    # ... various constant, class and method definitions ...
    
    def main():
        print("Hello World!")
    
    if __name__ == "__main__":
        main()
    
  2. Escreva um módulo Python que importe o módulo principal do seu programa Python, aguarde um sinal e invoque o método main do módulo principal:

    #!/usr/bin/env python3
    import signal, MyMainModule
    # Perform other initialisation tasks if necessary
    signal.sigwaitinfo((signal.SIGCONT,))
    MyMainModule.main()
    

    Se você não pode usar o Python 3, você pode consultar o equivalente Signal.sigwaitinfo do Python 3 no Python 2.7? para algo equivalente no Python 2.

  3. Inicie uma tarefa de "serviço" do Upstart com o programa Python anterior em some_boot_event . Vamos chamá-lo de my_service_task .

  4. Inicia uma segunda tarefa “one-shot” do Upstart em stopped hw_boot que envia um sinal CONT para a tarefa anterior:

    set -e
    kill -s CONT -- "$(initctl status my_service_task | grep -oEe '[0-9]+$')"
    

Se você precisar relatar informações de status de my_service_task para a tarefa na etapa 4, poderá configurar uma FIFO antes de enviar o sinal na última:

#!/usr/bin/env python3
import errno, signal, MyMainModule
# Perform other initialisation tasks if necessary

signal.sigwaitinfo((signal.SIGCONT,))
try:
    return_value = MyMainModule.main()
except Exception as ex:
    return_value = ex
try:
    with open("/var/run/my_service_task.status") as status_fifo:
        print(return_value, file=status_fifo)
except OSError as ex:
    if ex.errno not in (errno.ENOENT, errno.EPIPE):
        raise ex
if isinstance(return_value, Exception):
    raise return_value

No final da leitura:

set -e
STATUS_FIFO=/var/run/my_service_task.status
mkfifo -m 0600 "$STATUS_FIFO"
trap 'rm -f "$STATUS_FIFO"' 0 INT QUIT TERM

kill -s CONT -- "$(initctl status my_service_task | grep -oEe '[0-9]+$')"

read return_value < "$STATUS_FIFO"
# Do stuff with $return_value
    
por David Foerster 19.08.2017 / 12:31