In this lesson, you will learn how to guarantee your automation tasks complete gracefully by hooking custom scripts directly into the system shutdown sequence using systemd.
When a system initiates a shutdown, systemd sends a SIGTERM signal to running services. While many services stop immediately, your automation tasks—such as flushing database buffers, uploading final logs, or committing state files to remote storage—might need a specific execution window that occurs after standard services stop but before the hardware powers down.
Leveraging Unit Hooks for Shutdown
To ensure a task runs during shutdown, we create a specialized systemd unit file. The secret lies in the [Unit] and [Service] sections, where we define dependencies to ensure the task triggers at the correct time.
Create a service file like /etc/systemd/system/graceful-cleanup.service:
[Unit]
Description=Perform Final Automation Cleanup
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup-script.sh
TimeoutStartSec=0
[Install]
WantedBy=shutdown.target reboot.target halt.target
Understanding the Mechanics
DefaultDependencies=no: This is critical. By default,systemdunits include dependencies that might stop your service too early. Disabling this gives you full control over when your service executes.Before=shutdown.target: By declaring that your unit must run before these targets, you ensure that the system holds the shutdown process in a suspended state until yourExecStartscript finishes its job.Type=oneshot: This tellssystemdto wait for the process to exit completely before moving to the next step in the shutdown sequence.
If your script takes a long time to complete, be mindful that systemd will eventually send a SIGKILL if the timeout is exceeded. You can extend this window by adding TimeoutStopSec=30 to your [Service] section to provide sufficient buffer for your cleanup tasks to finalize.
By hooking into the shutdown target, you transform your automation from a collection of "best-effort" scripts into a robust pipeline that guarantees state consistency even when the system is powering off.
Key Takeaway: By using Before=shutdown.target and DefaultDependencies=no, you can force the system to wait for your critical automation cleanup tasks to finish before completing the power-off sequence.