¿La mejor manera de hacer un gancho de apagado?

9

Dado que Ubuntu se basa en el arranque desde hace algún tiempo, me gustaría usar un trabajo de arranque para cerrar con gracia ciertas aplicaciones al apagar o reiniciar el sistema. Es esencial que el apagado o reinicio del sistema se detenga hasta que se cierren estas aplicaciones.

Las aplicaciones se iniciarán manualmente de vez en cuando, y en el apagado del sistema debería finalizar automáticamente mediante un script (que ya tengo). Dado que las aplicaciones no se pueden finalizar de manera confiable sin (casi todos) otros servicios en ejecución, la finalización de las aplicaciones debe realizarse antes de que comience el resto del apagado.

Creo que puedo resolver esto con un trabajo inicial que se activará en el apagado, pero no estoy seguro de qué eventos debo usar de qué manera. Hasta ahora, he leído las siguientes declaraciones (en parte contradictorias):

  • No hay un evento de apagado general en el arranque
  • Use una estrofa como start on starting shutdownen la definición de trabajo
  • Use una estrofa como start on runlevel [06S]en la definición de trabajo
  • Use una estrofa como start on starting runlevel [06S]en la definición de trabajo
  • Use una estrofa como start on stopping runlevel [!06S]en la definición de trabajo

De estas recomendaciones, surgen las siguientes preguntas:

  • ¿Hay o no hay un evento de apagado general en el advenedizo de Ubuntu?
  • ¿Cuál es la forma recomendada de implementar un "gancho de apagado"?
  • Cuándo se activan los eventos runlevel [x]; ¿Es esto al entrar en el nivel de ejecución o al ingresar al nivel de ejecución?
  • ¿Podemos usar algo como start on starting runlevel [x]o start on stopping runlevel [x]?
  • ¿Cuál sería la mejor solución para mi problema?

Muchas gracias

Binarus
fuente

Respuestas:

2

startingy runlevelson eventos separados, por lo que no se puede decir de manera significativa starting runlevel N.

El runlevel Nevento se emite al comienzo de ingresar al nivel de ejecución. Si usted start on runlevel Nentonces su tarea se ejecuta en la entrada. La forma de ejecutar cuando se completa la entrada al nivel de ejecución es run on started rc RUNLEVEL=N.

Según tengo entendido, necesitas start on runlevel [06S]hacer lo que quieras; en teoría debería ejecutarse antes de que se detenga cualquier otra cosa. Para un control más preciso, puede usarlo start on stopping apache or stopping mysql or ...para que su tarea se ejecute antes de que cualquiera de ellos pueda cerrarse.


Editado para cambiar el nivel de ejecución 5 a S.

geekosaur
fuente
1
Además, la única razón por la que hay un startupevento distinguido es que se necesita algo para "cebar la bomba". Después de que se envía un evento privilegiado, todo lo demás puede definirse, y se define, por los trabajos y tareas activados por startup. En cuanto a que no haya un solo shutdownevento, hay demasiados tipos diferentes shutdownpara que eso sea significativo. Es mejor depender directamente de los trabajos que necesita tener en ejecución.
geekosaur
Muchas gracias. Agradezco su respuesta, ya que responde mis preguntas y resuelve el problema. Sin embargo, tengo una pregunta / comentario adicional (que no está relacionado con un problema): AFAIK, el objetivo inicial es reemplazar completamente el concepto de nivel de ejecución. El hecho de que necesitemos confiar en los niveles de ejecución para obtener un gancho de cierre global contradice este objetivo. Creo que el advenedizo tendrá que presentar tal evento. Entiendo claramente que sería mejor depender de los trabajos que realmente necesitamos, pero por otro lado, en mi caso, es un montón de trabajos ... cont ...
Binarus
(casi todo lo que se está ejecutando), e incluso no me atrevo a pensar en averiguar la relación entre los procesos que se ejecutan en la caja (ps -Alf) y los trabajos que controlan estos procesos; seguro que no hay una relación 1: 1. Hay trabajos que no están relacionados con ningún proceso (configurando la red, por ejemplo), y supongo que hay suficientes procesos que no están relacionados con los trabajos de todos modos y especialmente cuando se inician las cosas manualmente.
Oli
Upstart reemplazó los niveles de ejecución codificados ; Por lo que puedo determinar, el concepto de nivel de ejecución no va a desaparecer, solo se define en el espacio de usuario ahora. Si está preocupado por un plazo tan largo, entonces desea utilizar mi última sugerencia de ejecución on stopping servicea or stoping serviceb or ...para cualquier servicio que necesite tener en ejecución.
geekosaur
-1 por varias imprecisiones. De plano, esto en realidad no funcionará. detener al iniciar rc RUNLEVEL = [016] no es diferente desde 'detener en el nivel de ejecución [016]'. Esto se debe a que ninguno de los eventos bloqueará el proceso de apagado. También hay una sintaxis no válida, ya que 'ejecutar en' no es válido. En general, esto solo confunde el problema, en realidad no ayuda. Lamento que esto sea tan tarde! Solo estoy revisando viejas respuestas.
SpamapS
2

Para evitar que continúe el apagado mientras se detiene su trabajo, querrá usar esto:

stop on starting rc RUNLEVEL=[016]

Esto funcionará porque lo primero que sucede cuando escribe 'shutdown' es que se emite tunlevel 0. rc comienza en el nivel de ejecución, y la transición de parado -> inicio se bloqueará por completo hasta que cualquier trabajo que también deba cambiar de estado complete ese estado.

Deberá asegurarse de que su proceso responda rápidamente a SIGTERM. Si no responde en 5 segundos, el arranque lo enviará SIGKILL. Puedes aumentar eso con 'kill timeout X'.

El 1 allí, por cierto, es un poco complicado, debe asegurarse de que su inicio incluye algo que comience en el nivel de ejecución [2345] en ese punto, de modo que un usuario que se retira para el mantenimiento del modo de usuario único comience su trabajo nuevamente. Afortunadamente, se ha invertido mucho trabajo para que este sea el comienzo habitual sugerido en

start on runlevel [2345]

Además, en algunos casos, necesita algo para seguir funcionando hasta que la red se caiga (como dbus / network-manager). Para eso quieres

stop on deconfiguring-networking

Ese es un evento emitido más tarde en el apagado que también se bloqueará hasta que cualquier trabajo que lo use complete completamente sus transiciones en estado.

SpamapS
fuente
¿Querías decir start on starting ... que no tiene mucho sentido que mi gancho de apagado se detenga en nada? start on starting rc RUNLEVEL=[016]Tendría mucho más sentido. Y tal vez un tasklanzamiento allí para garantizar que pueda completarse antes de que se ejecuten otras cosas.
Tejay Cardon
0

Geekosaur, muchas gracias por tu ayuda.

Mientras tanto, probé el start on runlevel [016]método, pero no funcionó, y creo que entiendo por qué:

El trabajo ya se inició, pero el proceso de apagado no se bloqueó hasta que finalizó la tarea del trabajo. Ahora estoy bastante seguro de que los eventos startingy stoppingson los únicos eventos que se pueden usar en una definición de trabajo para bloquear otros trabajos, y creo que esto es lo que los manuales de Upstart intentan decirnos. Por lo tanto, usar el evento runlevel nunca conducirá al bloqueo de otros trabajos o al proceso de apagado; por lo tanto, es inútil para mi propósito.

En cambio, parece que tengo dos posibilidades:

  1. Siguiendo una de sus propuestas, descubra todos los trabajos que necesitan las aplicaciones respectivas e inclúyalos en el evento de inicio para el script de esta manera:

    start on stopping job1 or stopping job2 or ...
    

    Esto es tanto trabajo que estoy pensando seriamente en eliminar la lista de trabajos y ejecutarla a través de sed para producir automáticamente una estrofa de inicio para mi trabajo que incluye todos los trabajos que normalmente se ejecutan en el sistema.

    La ventaja sería que las aplicaciones respectivas se cerrarían incluso cuando alguien detuviera uno de los requisitos previos manualmente (en lugar de detenerlos mediante un cambio / apagado / reinicio de nivel de ejecución).

  2. Encuentre el único trabajo que se detendrá al principio cuando reinicie / apague el sistema (llamemos a este trabajo "FirstJob") y use ese trabajo en una estrofa como:

    start on stopping FirstJob
    

    Las principales desventajas serían que no sé si tal trabajo existe en absoluto y si ese trabajo realmente depende de todos los demás trabajos de los que realmente depende la aplicación respectiva ("depende de otro trabajo" en este caso significa "se detendrá" completamente antes de que otro trabajo comience a detenerse ").

No estoy seguro de cuál de las dos posibilidades es la mejor ...

Binarus
fuente
Estaría haciendo el sedguión ahora mismo, si estuviera en tu lugar.
geekosaur