How to run commands at shutdown on Linux

Linux and Unix systems have long made it pretty easy to run a command on boot. Just add your command to /etc/rc.local and away you go. But as it turns out, running a command on shutdown is a little more complicated.
Why would you want to run a command as the computer shuts down? Perhaps you want to de-register a machine or service from a database. Maybe you want to copy data from a volatile storage system to a permanent location. Want your computer to post "#RIP me!" on its Twitter account before it shuts down?
I should clarify at this point that I'm talking about so-called "one-shot" commands as opposed to stopping a daemon. It's tempting to think of them the same way, though. If you're familiar with SysVinit you might think, "Oh, I'll just create a kill script." For example, /etc/rc.d/rc3.d/K99runmycommandatshutdownshould get invoked when your system exits runlevel 3. After all, that's how the scripts in /etc/init.d/ get stopped.
That's a great guess, but it turns out that it's wrong. SysVinit does not blindly run the kill scripts. Instead, it looks for (on Red Hat 6) /var/lock/subsys/service_name (where service_name here would be runmycommandatshutdown). So you have to get a little bit tricky and treat your script like a regular service. The script below gives an example:
#!/bin/sh
# chkconfig: 2345 20 80
# description: An example init script to run a command at shutdown
 
# runmycommandatshutdown runs a command at shutdown. Very creative.
 
LOCKFILE=/var/lock/subsys/
start(){
    # Touch our lock file so that stopping will work correctly
    touch ${LOCKFILE}
}
 
stop(){
# Remove our lock file
rm ${LOCKFILE}
# Run that command that we wanted to run
mycommand
}
 
case "$1" in
    start) start;;
    stop) stop;;
    *)
        echo $"Usage: $0 {start|stop}"
        exit 1
esac
exit 0
After putting that script in /etc/init.d/runmycommandatshutdown and enabling it with chkconfig on runmycommandatshutdown, your command will be run at shutdown.

systemd

All of that is great, but what if you're running a distribution of Linux that uses systemd instead of SysVinit? Turns out, it's much simpler with systemd. All you have to do is put your script in /usr/lib/systemd/system-shutdown/, which is handled by systemd-halt.service. Of course, if you need to manage dependencies in a particular order (e.g., you can't post a tweet if the network stack is down), then you can write a systemd service unit file. For example:
[Unit]
Description=Run mycommand at shutdown
Requires=network.target
DefaultDependencies=no
Before=shutdown.target reboot.target
 
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=mycommand
 
[Install]
WantedBy=multi-user.target


EmoticonEmoticon