Run a Script at Shutdown Only (Not on Reboot) with systemd

Deepak Prasad
Tested on RHEL 10.2 (Coughlan) — vm1.lab.example
Package systemd 257-23.el10_2.2
Applies to Ubuntu, Debian, Kali Linux, Linux Mint, Pop!_OS, Raspberry Pi OS, elementary OS, Zorin OS, Parrot OS, MX Linux, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora, Arch Linux
Privilege sudo or root
Scope Run a oneshot script only during poweroff or halt by enabling on poweroff.target and halt.target, and confirm reboot does not append a log line. Does not cover long-running services stopped with ExecStop.
Related guides Run script before shutdown
Linux boot reboot shutdown
Create a systemd service
systemctl command
Beginners guide to systemd

Poweroff and halt end the machine; reboot brings it back up. Both involve shutdown work, but you may want a script only when the system is going off — for example flushing a local backup before power is removed.

Enable the unit on poweroff.target and halt.target, not on reboot.target. That way reboot never pulls your service into its transaction.


Create the shutdown script

The script appends a timestamp when poweroff or halt runs it:

bash
sudo tee /usr/local/sbin/shutdown-only-task.sh <<'EOF'
#!/bin/bash
LOG=/var/log/shutdown-only-task.log
echo "time=$(date -Is) event=poweroff_or_halt" >> "$LOG"
EOF

Make it executable:

bash
sudo chmod 755 /usr/local/sbin/shutdown-only-task.sh

Create the systemd unit

Create /etc/systemd/system/shutdown-only-task.service:

ini
[Unit]
Description=Run task at poweroff or halt only (not reboot)
DefaultDependencies=no
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/shutdown-only-task.sh

[Install]
WantedBy=poweroff.target halt.target

WantedBy=poweroff.target halt.target is what makes the service shutdown-only. systemctl enable creates links under those targets, but not under reboot.target, so reboot does not pull this unit in.

Before=shutdown.target places the script before the general shutdown synchronization point rather than at the very end of poweroff. If your task depends on another service or mount, give that dependency explicit ordering.


Reload and enable

Reload unit definitions after editing the file:

bash
sudo systemctl daemon-reload

Enable the unit on poweroff and halt targets:

bash
sudo systemctl enable shutdown-only-task.service

Sample output:

output
Created symlink '/etc/systemd/system/poweroff.target.wants/shutdown-only-task.service' → '/etc/systemd/system/shutdown-only-task.service'.
Created symlink '/etc/systemd/system/halt.target.wants/shutdown-only-task.service' → '/etc/systemd/system/shutdown-only-task.service'.

Verify shutdown-only behavior

After enabling, the unit should run for poweroff or halt, but not for reboot.

Power off the test VM (console or hypervisor — not reboot):

bash
sudo poweroff

After the machine is back on, read the log:

bash
sudo cat /var/log/shutdown-only-task.log

Sample output from lab testing:

output
time=2026-08-21T11:13:42+05:30 event=poweroff_or_halt

If you also test with reboot, no new timestamp should be added to that file — that confirms reboot did not start the unit.


Troubleshooting

Symptom Likely cause Fix
Script runs on reboot Unit enabled on shutdown.target instead Use WantedBy=poweroff.target halt.target only
No log line after poweroff Unit not enabled Confirm symlinks under poweroff.target.wants and halt.target.wants
Script also needed on reboot Wrong guide Use before shutdown unit instead

References

Summary

Shutdown-only behavior comes from WantedBy=poweroff.target halt.target — that decides when the unit participates: poweroff and halt, but not reboot. Before=shutdown.target decides when inside those shutdown transactions it runs.

Verify with poweroff and check the log file. If you need the same script on reboot and poweroff, use the before shutdown guide instead.


Frequently Asked Questions

1. Why not use the same unit for reboot and shutdown?

Reboot and poweroff both pass through the generic shutdown process. Hook this unit to poweroff.target and halt.target only so reboot.target never pulls it in.

2. Do I need Conflicts=reboot.target or script logic to detect reboot?

No. When the unit is enabled on poweroff.target and halt.target, systemd starts it only for poweroff or halt. The script can perform its task without inspecting list-jobs.

3. Does this replace ExecStop on my application service?

No. Use this when you need a global shutdown hook independent of which applications were running.
Omer Cakmak

Linux Administrator

Highly skilled at managing Debian, Ubuntu, CentOS, Oracle Linux, and Red Hat servers. Proficient in bash scripting, Ansible, and AWX central server management, he handles server operations on OpenStack, KVM, Proxmox, and VMware.

  • Debian
  • Ubuntu
  • Linux
  • Red Hat Enterprise Linux
  • Shell Script
  • System Administration