In your unit file you are using ExecStart=
and yes, it is just doing what it is named: it will start the service. To run a script only on shutdown you have to use ExecStop=
so your Unit should look similar to this:
[Unit]
Description=Turn off tv and lights on shutdown
After=graphical.target
[Service]
Type=oneshot
RemainAfterExit=yes
User=pi
WorkingDirectory==/home/pi
ExecStop=/full/path/to/irsend SEND_ONCE 'TVNAME' KEY_POWER
[Install]
WantedBy=graphical.target
UPDATE: because of the discussion in the comments, here some tests I have made to get an idea how it works.
Look at the properties to find runtime dependencies with:
rpi ~$ systemctl show shutdown-test.service
To get dependencies:
rpi ~$ systemctl list-dependencies shutdown-test.service
Documentation of the System Manager Shutdown phase.
To get shutdown messages from the systemd journal I made it persistent:
rpi ~$ sudo mkdir -p /var/log/journal
rpi ~$ sudo systemd-tmpfiles --create --prefix /var/log/journal
After reboot then look at the previous journal before booting with:
rpi ~$ journalctl --boot=-1
If you modify the [Install]
section, don`t forget to:
rpi ~$ sudo systemctl disable shutdown-test.service
rpi ~$ sudo systemctl enable shutdown-test.service
To be on the save side boot two times after modifying the Unit file. I have seen situations where on first boot only the changes are registered and take effect after the second boot. Use correct targets as shown in System Manager Shutdown, in particular with WantedBy
.
Test Case 1:
[Unit]
Description=Shutdown Test
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/bin/echo 'shutdown test executed'
[Install]
WantedBy=reboot.target poweroff.target halt.target kexec.target
# dependencies
shutdown-test.service
● └─system.slice
rpi ~$ journalctl --boot=-1 --unit=shutdown-test.service
-- Logs begin at Sat 2020-03-07 14:45:36 GMT, end at Sat 2020-03-07 18:41:01 GMT. --
Mar 07 18:40:04 raspberrypi systemd[1]: Starting Shutdown Test...
Mar 07 18:40:05 raspberrypi echo[708]: shutdown test executed
Mar 07 18:40:06 raspberrypi systemd[1]: shutdown-test.service: Succeeded.
Mar 07 18:40:06 raspberrypi systemd[1]: Started Shutdown Test.
Note that the service is only started in the general shutdown stage but not stopped. This is for my opinion not a clean service management. In the shutdown stage there should services only stop not start.
# snippet from the journal
rpi ~$ journalctl --boot=-1 | egrep ' Stopp| Start| echo'
Mar 07 18:48:32 raspberrypi systemd[1]: Stopping LVM event activation on device 179:2...
Mar 07 18:48:32 raspberrypi systemd[1]: Stopped target Graphical Interface.
^^^^^^^
Mar 07 18:48:32 raspberrypi systemd[1]: Stopped target Multi-User System.
^^^^^^^
Mar 07 18:48:32 raspberrypi systemd[1]: Stopping Availability of block devices...
Mar 07 18:48:32 raspberrypi systemd[1]: Stopped target Bluetooth.
Mar 07 18:48:32 raspberrypi systemd[1]: Stopping Bluetooth service...
Mar 07 18:48:32 raspberrypi systemd[1]: Starting Shutdown Test...
^^^^^^^^
Mar 07 18:48:32 raspberrypi systemd[1]: Stopped target Sound Card.
Mar 07 18:48:32 raspberrypi systemd[1]: Stopped target Login Prompts.
Mar 07 18:48:32 raspberrypi echo[715]: shutdown test executed
^^^^
Mar 07 18:48:32 raspberrypi systemd[1]: Stopping Serial Getty on ttyS0...
--- snip ---
Mar 07 18:48:33 raspberrypi systemd[1]: Started Shutdown Test.
^^^^^^^
Mar 07 18:48:33 raspberrypi systemd[1]: Stopped Save/Restore Sound Card State.
Mar 07 18:48:33 raspberrypi systemd[1]: Stopped dphys-swapfile - set up, mount/unmount, and delete a swap file.
Mar 07 18:48:33 raspberrypi systemd[1]: Stopped rng-tools.service.
As you can see there are no dependencies because they are disabled. So the Shutdown Test is started after Stopped target Graphical Interface and Multi-User System. Stopping services is random.
Test Case 2:
With DefaultDependencies=yes
the shutdown-test.service is never executed:
rpi ~$ journalctl --boot=-1 --unit=shutdown-test.service
-- Logs begin at Sat 2020-03-07 14:55:33 GMT, end at Sat 2020-03-07 19:06:49 GMT. --
-- No entries --
Test Case 3:
[Unit]
Description=Shutdown Test
After=graphical.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStop=/bin/echo 'shutdown test executed'
[Install]
WantedBy=graphical.target
rpi ~$ journalctl --boot=-1 --unit=shutdown-test.service
-- Logs begin at Sat 2020-03-07 14:56:33 GMT, end at Sat 2020-03-07 19:14:00 GMT. --
Mar 07 19:12:19 raspberrypi systemd[1]: Started Shutdown Test.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopping Shutdown Test...
Mar 07 19:13:03 raspberrypi echo[715]: shutdown test executed
Mar 07 19:13:03 raspberrypi systemd[1]: shutdown-test.service: Succeeded.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped Shutdown Test.
# snippet from the journal
Mar 07 19:13:03 raspberrypi systemd[1]: Stopping Bluetooth service...
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped Daily apt download activities.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped target System Time Synchronized.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopping Shutdown Test...
^^^^^^^^
Mar 07 19:13:03 raspberrypi echo[715]: shutdown test executed
^^^^
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped Bluetooth service.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped LVM event activation on device 179:2.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped Shutdown Test.
^^^^^^^
Mar 07 19:13:03 raspberrypi systemd[1]: Stopping User Manager for UID 1000...
Mar 07 19:13:03 raspberrypi systemd[649]: Stopped target Default.
Mar 07 19:13:03 raspberrypi systemd[649]: Stopped target Basic System.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped target Graphical Interface.
^^^^^^^
Mar 07 19:13:03 raspberrypi systemd[649]: Started Exit the Session.
Mar 07 19:13:03 raspberrypi systemd[1]: Stopped target Multi-User System.
^^^^^^^
Mar 07 19:13:03 raspberrypi systemd[1]: Stopping Login Service...
Mar 07 19:13:03 raspberrypi systemd[1]: Stopping dphys-swapfile - set up, mount/unmount, and delete a swap file...
Here is everything as expected. The service is starting on bootup and stopping within the shutdown stage like any other service. We have default dependencies and defined After=graphical.target
in the Unit, which ensures that the Shutdown Test stops before target Graphical Interface. So my suggestion is: to avoid problems with dependencies you should use this Unit as template.
If your shutdown script still doesn't run, you should check if it find the same environment when starting from the command line. Maybe there is a path, environment variable, or library missing. Check the journal for error messages, execute systemctl status myservice.service
. I have modified the Unit file to possibly meet some of these conditions.