Running a shell script at shutdown only (not at reboot) – a comparison between OpenRC and systemd

Gentoo Linux on my laptops uses OpenRC with SysVinit, whereas Lubuntu 17.10 on my family’s PC uses systemd. I have had to configure both Linux distributions to run a backup job at shutdown, so I thought it would be interesting to summarise the two approaches.

OpenRC

Create a Bash script /etc/local.d/10-run_on_shutdown.stop with the following contents:

#!/bin/bash
if [ `who -r | awk '{print $2}'` = "0" ]; then
    ########################################################################
    # Put Bash commands here to be executed on shutdown but not on reboot. #
    # For example, backup home directories to an external USB HDD.         #
    ########################################################################
fi

From now on the script will run to completion when you shutdown the machine, but not when you reboot it.

systemd

1. Create a Bash script /usr/local/sbin/run_on_shutdown.sh with the following contents:

#!/bin/bash
REBOOT=$( systemctl list-jobs | egrep -q 'reboot.target.*start' && echo "rebooting" || echo "not_rebooting" )
if [ $REBOOT = "not_rebooting" ]; then
    ########################################################################
    # Put Bash commands here to be executed on shutdown but not on reboot. #
    # For example, backup home directories to an external USB HDD.         #
    ########################################################################
fi

2. Create a unit file /etc/systemd/system/run_on_shutdown.service with the following contents:

[Unit]
Description=Run a Bash script at shutdown
DefaultDependencies=no
Before=shutdown.target halt.target
# If your script requires any mounted directories, add them below: 
RequiresMountsFor=/home

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/run_on_shutdown.sh

[Install]
WantedBy=halt.target shutdown.target

I have assumed the Bash script is to backup /home, so change the directory list in ‘RequiresMountsFor=‘ if the script necessitates that other directories are still mounted – see ‘man systemd.unit‘ for details.

3. Enable the unit file and start the service as follows:

user $ sudo systemctl enable run_on_shutdown.service
user $ sudo reboot

From now on, the script will run to completion when you shutdown the machine, but not when you reboot it.

Notes on the systemd solution:

There are plenty of posts on the Web suggesting how to run a script at shutdown in installations that use systemd, but the approaches either do not work in my case or they do not discriminate between shutting down and rebooting. For example, if you are wondering why I do not use ‘Conflicts=reboot.target‘ in the unit file, I found it does not prevent the Bash script from being launched when the system is rebooted (see the entry for ‘Conflicts=‘ in ‘man systemd.unit‘ for the functionality). If you are wondering why I do not simply place a script in /lib/systemd/system-shutdown/, it is because scripts in that directory are launched late in the shutdown process, after file systems have been mounted read-only. And if you are wondering why the Bash script tests if the system is rebooting (as distinct from shutting down) rather than the unit file being configured to do that, it is because the systemd shutdown target is active in any type of system termination, be it rebooting or halting, and it therefore does not help in discriminating between the termination types (see ‘man systemd.special‘). I tried several approaches in the unit file to see if it could be made to launch a Bash script when shutting down but not when rebooting, but the only solution that works for me in the Lubuntu 17.10 installation on my family’s PC uses the two files listed above working in conjunction with each other.

Furthermore, of all the unit files I found on the Web that actually make systemd launch a Bash script when a user initiates shutdown, only one of them prevents systemd from shutting down the machine before a time-consuming script has run to completion (for example a script to backup to an external HDD). I also tried using systemd-inhibit in this case, and it did not work. Looking at the manual page for systemd-inhibit, it could be used to execute a program (the example given is ‘systemd-inhibit wodim foobar.iso‘), however I found that systemd-inhibit did not prevent systemd from shutting down the machine before a Bash script to backup a single-seat, multi-user installation had run to completion.

Some background reading

  1. Easy Systemd Startup and Shutdown Scripts for Ubuntu 16.04 and Mint 18
  2. Stack Exchange Super User : How do I run a script before everything else on shutdown with systemd?
  3. Stack Overflow : how can a systemd controlled service distinguish between shutdown and reboot?
  4. Unix & Linux Stack Exchange : Systemd : How to execute script at shutdown only (not at reboot)

About Fitzcarraldo
A Linux user with an interest in all things technical.

4 Responses to Running a shell script at shutdown only (not at reboot) – a comparison between OpenRC and systemd

  1. Pingback: Backing up users’ home directories in a Linux installation that uses systemd | Fitzcarraldo's Blog

  2. Pingback: Configure time consuming Shell script execution before shutdown linux instance – Mags Forum Technology

  3. Yevhenii Nadtochii says:

    It doesn’t work if script needs network-online.target. Particularly rclone utility.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.