89

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
  • 1,571

4 Answers4

107

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.

rsaw
  • 1,006
Matthias
  • 1,086
  • 9
    At ubuntu 16.04 you must have a ExecStart=/bin/true. – niels Dec 29 '16 at 20:50
  • 8
    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. – Felipe Alvarez Jun 15 '17 at 00:30
  • 1
    Is there anyway to ensure this script will run and complete before user sessions and user processes are terminated? – richmb Oct 19 '17 at 13:19
  • @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. – svenwltr Nov 30 '17 at 11:19
  • I've tried this and various iterations on it but it does not work on Debian Stretch. – 2rs2ts Sep 21 '18 at 01:02
  • 2
    @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? – Charles Duffy Sep 26 '19 at 19:46
  • 1
    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. – Aspiring Dev May 04 '20 at 17:26
25
  • 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

  • 9
    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. – Jaime Hablutzel May 25 '19 at 22:29
  • 1
    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. – maxschlepzig Jun 21 '20 at 10:05
  • @JaimeHablutzel Are you able to achieve? – ImranRazaKhan Jul 29 '20 at 22:08
  • Within Yocto, scripts can be put in the folder /lib/systemd/system-shutdown/. – Joël Esponde Aug 07 '23 at 15:59
10

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
Ulrich Dangel
  • 25,369
  • When I try this the script gets executed soon after the start (boot). – sid_com May 24 '12 at 08:05
  • @sid_com After reading http://thread.gmane.org/gmane.comp.sysutils.systemd.devel/4515/focus=4560 try to add DefaultDependencies=no and maybe remove the install section. Otherwise it may help to remote the after/requires lines. – Ulrich Dangel May 24 '12 at 11:56
10

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
tshepang
  • 65,642
sid_com
  • 1,571
  • 4
    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). – RDP Jan 29 '16 at 01:01
  • You may want to add kexec.target to the Before bit – hanetzer Mar 26 '16 at 11:11
  • This doesn't work for me – Bug Killer Sep 07 '16 at 01:50
  • 4
    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. – rsaw Sep 08 '16 at 15:57
  • This answer doesn't solve the problem where you need something to run before other things shut down – 2rs2ts Sep 21 '18 at 01:35