How do I run a script before everything else on shutdown with systemd?

30,888

Solution 1

I got it!

Take solution Long running process with StopExec and modify it like so:

autobackup.service:

[Unit]
Description=Slow backup script
RequiresMountsFor=/mnt/BACKUP /home

[Service]
ExecStop=/etc/systemd/system/do_backup.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Note the line:

RequiresMountsFor=/mnt/BACKUP /home

It works as expected this way.

Solution 2

No need to create or edit service files. Simply drop your script in

/usr/lib/systemd/system-shutdown/

https://www.freedesktop.org/software/systemd/man/systemd-halt.service.html

Immediately before executing the actual system halt/poweroff/reboot/kexec systemd-shutdown will run all executables in /usr/lib/systemd/system-shutdown/ and pass one arguments to them: either "halt", "poweroff", "reboot" or "kexec", depending on the chosen action. All executables in this directory are executed in parallel, and execution of the action is not continued before all executables finished.

I use it to simply beep the PC speaker.

Share:
30,888

Related videos on Youtube

le_me
Author by

le_me

Updated on September 18, 2022

Comments

  • le_me
    le_me over 1 year

    Note: Briefly formulated question can be found at the bottom.

    I have a script which makes a backup of my files onto an external USB drive. Executing it can take a while, depending on the amount of new data I've created. I want to run it automatically on every shutdown of the system.

    I'm using fedora 23 with latest updates (systemd).

    I tried to achieve this in several ways, but I couldn't get it to work.

    Long running process with StopExec

    autobackup.service:

    [Unit]
    Description=Slow backup script
    Requires=local-fs.target
    
    [Service]
    ExecStart=/bin/true
    ExecStop=/etc/systemd/system/do_backup.sh
    Type=oneshot
    RemainAfterExit=yes
    
    [Install]
    WantedBy=multiuser.target
    

    I activated it with systemctl enable autobackup.service and started it with systemctl start autobackup.service.

    Part of my boot log (journalctl -b-1):

    Dez 22 17:45:27 localhost systemd[1]: Unmounted /mnt/BACKUP.
    Dez 22 17:45:27 localhost do_backup.sh[4296]: At subvol /home/BACKUP.2015_12_22-17_45_25
    Dez 22 17:45:27 localhost do_backup.sh[4296]: ERROR: parent subvol is not reachable from inside the root subvol.
    Dez 22 17:45:27 localhost do_backup.sh[4296]: At snapshot BACKUP.2015_12_22-17_45_25
    Dez 22 17:45:27 localhost do_backup.sh[4296]: ERROR: failed to dump stream. Broken pipe
    Dez 22 17:45:27 localhost systemd[1]: autobackup.service: Control process exited, code=exited status=1
    Dez 22 17:45:27 localhost systemd[1]: Stopped Slow backup script.
    Dez 22 17:45:27 localhost systemd[1]: autobackup.service: Unit entered failed state.
    

    Note that I didn't shorten anything in between, it really unmounted /mnt/BACKUP just before the script started, funny coincidence..

    Before shutdown.target

    autobackup.service:

    [Unit]
    Description=Slow backup script
    DefaultDependencies=no
    Before=shutdown.target
    
    [Service]
    ExecStart=/etc/systemd/system/do_backup.sh
    Type=oneshot
    

    systemctl edit shutdown.target

    [Unit]
    Requires=autobackup.service
    

    Output is basically the same.

    The Problem

    I think the problem is that systemd starts my script in parallel with all the other shutdown scripts in both cases, which unmount BACKUP and deactivate the pipe infrastructure (another error I sometimes got, when the unmount wasn't fast enough).

    The Question

    How can I teach systemd to start my script first on shutdown, wait until it exits and then start the rest of the shutdown scripts/targets/units/whatever?

  • Stefan Majewsky
    Stefan Majewsky about 8 years
    You shouldn't need to do the systemctl edit. systemctl enable autobackup has the same effect and is more idiomatic, and should work since you already have the [Install] section in your unit. You will have to correct that typo in the target name, though. ;)
  • WoJ
    WoJ over 7 years
    Did you have to make this directory? I do not have it neither on Ubuntu 16.04 nor Raspbian (jessie) - both are systemd based.
  • Frank Breitling
    Frank Breitling about 7 years
    Debian systems use the different path /lib/systemd/system-shutdown/. And in addition be aware that these scripts are executed very late in shutdown, after file systems are already mounted read-only. So any write access to the file system will fail unless remounted as read-write (mount -oremount,rw /). See How to execute scripts in /usr/lib/systemd/system-shutdown/ at reboot or shutdown?
  • Greg Alexander
    Greg Alexander about 7 years
    OP asked for script executed "before everything else" on shutdown. The system-shutdown scripts are executed after everything else, immediately before killing the kernel.
  • 2rs2ts
    2rs2ts over 5 years
    This does not work for me. I don't have any mounts, I just want to make sure my script runs before other units shut down.