| 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 during shutdown and reboot before shutdown.target completes and verify with a persistent log file. Does not cover shutdown-only units that skip reboot. |
| Related guides | Run script at shutdown only not reboot Run script at boot after network Linux boot reboot shutdown Create a systemd service systemctl command |
This pattern starts your script whenever the machine is shutting down, whether the final action is reboot or poweroff. Use it when you want one system-wide cleanup script during every shutdown transition — not tied to a single application service.
shutdown.target is the systemd target used while the system is transitioning toward shutdown. systemd includes your service in that transaction through WantedBy=shutdown.target.
Do not assume another service such as a database or network connection is still available. If your script depends on one particular service, it is usually better to run that cleanup as part of that service's shutdown with ExecStop= — see create a systemd service.
When you need a script only on halt and not on reboot, use shutdown-only systemd unit instead.
Create the cleanup script
Append one line to a log file on each shutdown transition:
sudo tee /usr/local/sbin/before-shutdown-task.sh <<'EOF'
#!/bin/bash
LOG=/var/log/before-shutdown-task.log
echo "time=$(date -Is) shutdown_task_ran" >> "$LOG"
EOFMake it executable:
sudo chmod 755 /usr/local/sbin/before-shutdown-task.shCreate the shutdown service
Create /etc/systemd/system/before-shutdown-task.service:
[Unit]
Description=Run task before shutdown or reboot completes
DefaultDependencies=no
Before=shutdown.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/before-shutdown-task.sh
[Install]
WantedBy=shutdown.targetEnabling this unit makes systemd include it during the normal shutdown transaction on both reboot and poweroff.
WantedBy= decides which systemd transaction pulls the service in. Before= decides its ordering inside that transaction. Here, shutdown.target pulls it in for both reboot and poweroff, and Before=shutdown.target makes the script finish before that synchronization point.
This does not mean every other service is still running when your script starts.
Reload and enable
Reload unit definitions after editing the file:
sudo systemctl daemon-reloadEnable the unit for shutdown and reboot transitions:
sudo systemctl enable before-shutdown-task.serviceSample output:
Created symlink '/etc/systemd/system/shutdown.target.wants/before-shutdown-task.service' → '/etc/systemd/system/before-shutdown-task.service'.Verify after reboot or poweroff
Reboot or run sudo poweroff on a test VM. After the system is back, read the log the script writes:
sudo cat /var/log/before-shutdown-task.logSample output from lab testing:
time=2026-08-21T11:05:41+05:30 shutdown_task_ran
time=2026-08-21T11:13:41+05:30 shutdown_task_ranEach line shows the unit ran during a shutdown transition. To run only on poweroff and skip reboot, use the shutdown-only guide.
If persistent journal storage is enabled on your system, you can also inspect the previous boot:
journalctl -u before-shutdown-task.service -b -1 --no-pagerTroubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Script killed mid-run | Default timeout too low | Set a larger TimeoutStartSec= for legitimately long cleanup |
| Shutdown hangs | Script never exits | Fix the script; avoid TimeoutStartSec=0 unless intentional |
| Unit never runs | Not enabled to shutdown.target |
Re-run systemctl enable before-shutdown-task.service |
| Script needed on poweroff only | This pattern runs on reboot too | Use shutdown-only unit |
References
Summary
A shutdown hook uses WantedBy=shutdown.target so systemd pulls your script into reboot and poweroff shutdown transactions, and Before=shutdown.target so the script finishes before that synchronization point. Verify with the log file under /var/log/; use journalctl -b -1 only when persistent journal storage is available.
To run only on poweroff and skip reboot, use the shutdown-only pattern in the linked guide.

