How to run a script with systemd right before shutdown?

132,505

Solution 1

The suggested solution is to run the service unit as a normal service - have a look at the [Install] section. So everything has to be thought reverse, dependencies too. Because the shutdown order is the reverse startup order. That's why the script has to be placed in ExecStop=.

The following solution is working for me:

[Unit]
Description=...

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=<your script/program>

[Install]
WantedBy=multi-user.target

RemainAfterExit=true is needed when you don't have an ExecStart action.

After creating the file, make sure to systemctl daemon-reload and systemctl enable yourservice --now.

I just got it from systemd IRC, credits are going to mezcalero.

Solution 2

  • To run a service right before starting any of reboot/shutdown/halt/kexec services (i.e. in the last moment before root filesystem becomes remounted read-only) use this service config:

    [Unit]
    Description=Save system clock on shutdown
    DefaultDependencies=no
    After=final.target
    
    [Service]
    Type=oneshot
    ExecStart=/usr/lib/systemd/scripts/fake-hwclock.sh save
    
    [Install]
    WantedBy=final.target
    

    Enable it with:

    systemctl enable my_service.service
    
  • To run a script right before actual reboot/shutdown/halt/kexec (when you cannot write to the root filesystem, because it was remounted read-only) add this script executable to the /usr/lib/systemd/system-shutdown directory.

    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.

Also see:

https://www.freedesktop.org/software/systemd/man/bootup.html

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

Solution 3

As far as I can see this does what I need (but I don't know exactly why).

[Unit]
Description=Log Traffic
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target


[Service]
ExecStart=/usr/local/bin/perl /home/me/log_traffic.pl --stop
Type=oneshot

Solution 4

I am not totally sure but i don't think you need the install part though i added it explicitly. I also didn't test it but i think it should help you get started:

[Unit]
Description=Log Traffic
Requires=network.target
After=network.target
Before=shutdown.target
DefaultDependencies=no

[Service]
ExecStart=/home/me/so.pl
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=shutdown.target
Share:
132,505

Related videos on Youtube

sid_com
Author by

sid_com

Updated on September 18, 2022

Comments

  • sid_com
    sid_com over 1 year

    What do I need to put in the [install] section, so that systemd runs /home/me/so.pl right before shutdown and also before /proc/self/net/dev gets destroyed?

    [Unit]
    Description=Log Traffic
    
    [Service]
    ExecStart=/home/me/so.pl
    
    [Install]
    ?
    
  • sid_com
    sid_com almost 12 years
    When I try this the script gets executed soon after the start (boot).
  • sunnysideup
    sunnysideup almost 12 years
    @sid_com After reading thread.gmane.org/gmane.comp.sysutils.systemd.devel/4515/… try to add DefaultDependencies=no and maybe remove the install section. Otherwise it may help to remote the after/requires lines.
  • RDP
    RDP over 8 years
    It happens to work because of 2 things: 1) DefaultDependencies=no makes it ignores all dependencies and run "at first" on start and "at last" on stop, always respecting "Before" and "After" clauses. 2) It happens to have a Before clause on shutdown/reboot/halt targets, so it will run just before shutdown/reboot/halt is reached on stop (because they only run on stop it happens to do what you want).
  • hanetzer
    hanetzer about 8 years
    You may want to add kexec.target to the Before bit
  • Bug Killer
    Bug Killer over 7 years
    This doesn't work for me
  • rsaw
    rsaw over 7 years
    I don't see how this will work unless you also add WantedBy=shutdown.target reboot.target halt.target to the [Unit] section. Before= & After= don't change dependencies.
  • niels
    niels over 7 years
    At ubuntu 16.04 you must have a ExecStart=/bin/true.
  • Mcol
    Mcol almost 7 years
    My assumption to WHY RemainAfterExit=true is required when there is no ExecStart is because systemd will not attempt to run ExecStop if it thinks that the service is not running. RemainAfterExit=true causes systemd to believe that the service is running, thereby causing it to run ExecStop at shutdown.
  • richmb
    richmb over 6 years
    Is there anyway to ensure this script will run and complete before user sessions and user processes are terminated?
  • svenwltr
    svenwltr over 6 years
    @richmb Not at all. From the docs: Note that it is usually not sufficient to specify a command for this setting that only asks the service to terminate (for example, by queuing some form of termination signal for it), but does not wait for it to do so.
  • 2rs2ts
    2rs2ts over 5 years
    I've tried this and various iterations on it but it does not work on Debian Stretch.
  • 2rs2ts
    2rs2ts over 5 years
    This answer doesn't solve the problem where you need something to run before other things shut down
  • waitfor
    waitfor almost 5 years
    I want to execute something as near as possible after initiating a reboot, way before the final.target. Ideally I would like that it is the first thing being executed after the user do $ sudo reboot.
  • Charles Duffy
    Charles Duffy over 4 years
    @2rs2ts, can you clarify "does not work" with more specificity? Does the service not load? Does its ExecStop begin execution but get killed before the process is able to complete? Something else?
  • Aspiring Dev
    Aspiring Dev about 4 years
    It seems you still have to add ExecStart=/bin/true for this to work, adding RemainAfterExit=true (without ExecStart) was not enough for me to get this to work on Fedora.
  • maxschlepzig
    maxschlepzig almost 4 years
    I tested the first approach on RHEL 7 and the service is actually executed after the root-filesystem is remounted read-only. That means hwclock state can't be written to /etc/adjtime then. This behavior is also what I expected after looking at the linked chart - because the umount.target readonly-remounts the root filesystem and final.target depends on that target.
  • ImranRazaKhan
    ImranRazaKhan almost 4 years
    @JaimeHablutzel Are you able to achieve?