Melhor maneira de fazer um gancho de desligamento?

9

Como o Ubuntu conta com o upstart já há algum tempo, gostaria de usar um trabalho inicial para desligar corretamente determinados aplicativos no desligamento ou reinicialização do sistema. É essencial que o desligamento ou reinicialização do sistema seja interrompido até que esses aplicativos sejam desligados.

Os aplicativos serão iniciados manualmente de vez em quando, e no desligamento do sistema deve ser automaticamente finalizado por um script (que eu já tenho). Como os aplicativos não podem ser finalizados de maneira confiável sem que (quase todos) outros serviços estejam em execução, o encerramento dos aplicativos deve ser feito antes que o restante do desligamento seja iniciado.

Acho que posso resolver isso por um trabalho inicial que será acionado no desligamento, mas não tenho certeza de quais eventos devo usar de que maneira. Até agora, li as seguintes declarações (parcialmente contraditórias):

  • Não há nenhum evento geral de desligamento no upstart
  • Use uma estrofe como start on starting shutdown na definição do trabalho
  • Use uma estrofe como start on runlevel [06S] na definição do trabalho
  • Use uma estrofe como start on starting runlevel [06S] na definição do trabalho
  • Use uma estrofe como start on stopping runlevel [!06S] na definição do trabalho

A partir dessas recomendações, surgem as seguintes perguntas:

  • Existe ou não há um evento geral de desligamento no upstart do Ubuntu?
  • Qual é a maneira recomendada de implementar um "gancho de desligamento"?
  • Quando os eventos runlevel [x] são acionados; é isso quando você entra no nível de execução ou quando entra no nível de execução?
  • Podemos usar algo como start on starting runlevel [x] ou start on stopping runlevel [x] ?
  • Qual seria a melhor solução para o meu problema?

Muito obrigado

    
por Binarus 14.03.2011 / 21:51

3 respostas

2

starting e runlevel são eventos separados, por isso você não pode dizer de forma significativa starting runlevel N .

O evento runlevel N é emitido no início da entrada do nível de execução. Se você start on runlevel N , sua tarefa será executada na entrada. A maneira de executar quando a entrada para o nível de execução é concluída é run on started rc RUNLEVEL=N .

Pelo que entendi, você precisa de um start on runlevel [06S] para fazer o que quiser; deveria, em teoria, ser executado antes de qualquer outra coisa ser parada. Para um controle mais preciso, você pode usar start on stopping apache or stopping mysql or ... para que sua tarefa seja executada antes que qualquer um deles seja encerrado.

Editado para alterar o nível de execução 5 para S.

    
por geekosaur 14.03.2011 / 22:37
2

Para impedir que o desligamento continue enquanto seu trabalho para, você deverá usar isto:

stop on starting rc RUNLEVEL=[016]

Isso funcionará porque a primeira coisa que acontece quando você digita 'shutdown' é o nível 0 que é emitido. rc começa no nível de execução e a transição de parado - > Iniciar bloqueará completamente até que qualquer trabalho que também precise mudar de estado conclua esse estado.

Você precisará garantir que seu processo responda rapidamente ao SIGTERM. Se não responder dentro de 5 segundos, o upstart enviará o SIGKILL. Você pode aumentar isso com 'kill timeout X'.

O 1 lá, btw é um pouco complicado, você precisa ter certeza de que o seu início inclui algo que começa no nível de execução [2345] naquele ponto, para que um usuário descendo para manutenção de modo de usuário único inicie seu trabalho novamente. Felizmente, muito trabalho foi feito para que o começo usual sugerido em

start on runlevel [2345]

Além disso, em alguns casos, você precisa de algo para continuar funcionando até que a rede seja desativada (como dbus / network-manager). Para isso você quer

stop on deconfiguring-networking

Esse é um evento emitido posteriormente no desligamento que também será bloqueado até que qualquer trabalho que o use complete suas transições no estado.

    
por SpamapS 29.07.2012 / 08:50
0

Geekosaur, muito obrigado pela sua ajuda.

Nesse meio tempo, eu tentei o método start on runlevel [016] , mas não funcionou, e acho que entendi o porquê:

O trabalho foi iniciado de fato, mas o processo de desligamento não foi bloqueado até que a tarefa do trabalho tenha terminado. Tenho certeza agora que os eventos starting e stopping são os únicos eventos que podem ser usados em uma definição de tarefa para bloquear outros trabalhos, e acho que isso é o que os manuais do Upstart tentam nos dizer. Portanto, usar o evento runlevel nunca levará a bloquear outros trabalhos ou o processo de desligamento; assim, é inútil para o meu propósito.

Em vez disso, pareço ter duas possibilidades:

  1. Após uma de suas proposições, descubra todos os trabalhos que os respectivos aplicativos precisam e inclua todos eles no evento de início do script assim:

    start on stopping job1 or stopping job2 or ...
    

    Isso é muito trabalho que estou pensando seriamente em descarregar a lista de tarefas e executá-la através do sed para produzir automaticamente uma estrofe de início para o meu trabalho que inclui todas tarefas que normalmente estão em execução no sistema .

    A vantagem seria que os respectivos aplicativos seriam encerrados mesmo quando alguém interrompe um dos pré-requisitos manualmente (em vez de pará-los por uma mudança / encerramento / reinicialização do nível de execução).

  2. Encontre um trabalho que será interrompido no início ao reinicializar / desligar o sistema (vamos chamar esse trabalho de "PrimeiroJob") e usar esse trabalho em uma estrofe como:

    start on stopping FirstJob
    

    As principais desvantagens seriam que eu não sei se esse trabalho existe e se esse trabalho realmente depende de todos outros trabalhos dos quais o aplicativo em questão realmente depende ("depende de outro trabalho "neste caso significa" será interrompido completamente antes que outro trabalho comece a parar ").

Não sei qual das duas possibilidades é a melhor ...

    
por Binarus 17.03.2011 / 00:01