Best way to make a shutdown hook?

Solution 1:

starting and runlevel are separate events, so you can't meaningfully say starting runlevel N.

The runlevel N event is emitted at the start of entering the runlevel. If you start on runlevel N then your task runs on entry. The way to run when entry to the runlevel is completed is run on started rc RUNLEVEL=N.

As I understand it, you need a start on runlevel [06S] to do what you want; it should in theory run before anything else is stopped. For finer control you might use start on stopping apache or stopping mysql or ... so that your task runs before any of them are allowed to be shut down.


Edited to change runlevel 5 to S.

Solution 2:

In order to stop the shutdown from proceeding while your job stops, you will want to use this:

stop on starting rc RUNLEVEL=[016]

This will work because the first thing that happens when you type 'shutdown' is tunlevel 0 is emitted. rc starts on runlevel, and the transition from stopped -> starting will block completely until any jobs which also must change state do complete that state.

You'll want to make sure that your process responds quickly to SIGTERM. If it does not respond within 5 seconds, upstart will send it SIGKILL. You can raise that with 'kill timeout X'.

The 1 in there, btw is a bit tricky, you need to make sure your start on includes something that starts on runlevel [2345] at that point, so that a user going down for single user mode maintenance gets their job started again. Luckily a lot of work has gone into making this the suggested usual start on

start on runlevel [2345]

Also in some cases you need something to keep running right up until the network is brought down (such as dbus/network-manager). For that you want

stop on deconfiguring-networking

That is an event emitted later in the shutdown that will also be blocked on until any jobs that use it fully complete their transitions in state.