How to run a script just before halt using LSB headers on Raspbian

lsbraspbianshutdown

I'm building a shutdown button for my Raspberry pi, and for that I have a python script that needs to change a GPIO pin on my Raspberry Pi just before the system runs the halt script. Now Raspbian uses LSB headers to determine the order in which scripts are run at shutdown, but I can't for the life of me figure out what to put in the header so that the script will run AFTER everything except /etc/init.d/halt has run. The problem right now is that the script runs too soon (it always installs at K01xx), thus cutting the power before all other services have shut down properly.

I tried setting a custom priority as described in the guide here: http://www.debuntu.org/how-to-managing-services-with-update-rc-d/, but that does nothing as the command just says "using dependency based boot sequencing", with the end result being the same as before. I tried manually renaming the K01xx script in /etc/rc0.d to K09xx, so that it would be the last one before the halt command in the directory. But that had no effect either. Any suggestions?

My init.d script:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          shutdown
# Required-Start:    
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0
# Short-Description: Detect shutdown button
### END INIT INFO


PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_start() {
    if [ -x /home/pi/bin/shutdown.py ]; then
            [ "$VERBOSE" != no ] && log_begin_msg "Starting listening for shutdown button"
        python /home/pi/bin/shutdown.py &
        ES=$?
        [ "$VERBOSE" != no ] && log_end_msg $ES
        return $ES
    fi
}

do_stop() {
    if [ -x /home/pi/bin/shutdown_pin.py ]; then
        [ "$VERBOSE" != no ] && log_begin_msg "Lowering pin for complete shutdown"
        python /home/pi/bin/shutdown_pin.py
        ES=$?
        [ "$VERBOSE" != no ] && log_end_msg $ES
    fi
}

case "$1" in
    start)
    do_start
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop)
    do_stop
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

Best Answer

/etc/init.d/halt stops the system from running, so nothing is going to run after that. However, assuming you aren't doing anything else fancy at shutdown (like enabling wake on LAN) it should be safe to switch off the power after /etc/init.d/umountroot runs. It unmounts the root file system then remounts it read only. This way subsequent scripts can be read and run from disk without risk of corruption.

If you look in /etc/rc0.d you should see symlinks to files in /etc/init.d. On my system, I have:

... /etc/rc0.d/S60umountroot -> /etc/init.d/umountroot /etc/rc0.d/S90halt -> /etc/init.d/halt

Link your script to /etc/rc0.d/S80gpio_poweroff_signal and your gpio signal will be sent after the SD card is read only.

Thanks to Nate Powell for his help answering this.

Related Question