Setting up graceful shutdown

Hello everyone!

I’ve recently gotten an Uninterrupted Power Supply for my computer which I setup to shutdown my computer. In case the battery within the UPS were to ever run low on power, I expected the UPS to gracefully shutdown the computer to avoid abruptly closing down processes, however, in a recent power event it would seem that this did not occur. From what i can gather, it seems that the daemon that handles the shutdown is using systemctl poweroff which on my system immediately shuts off the computer without doing much to request processes to close themselves.

I did some research regarding how to potentially do this, and apparently there may be a way to do as such by sending sigterm signals to every process, allowing for a process to do what it needs to do before shutting off (ex. closing databases, saving documents, etc.). There is also something regarding systemctl where one may potentially be able to modify the behavior of units used by systemctl, like that of poweroff, but i fear modifying a built in unit may lead to unexpected issues down the road.

Is there a recommended way to set up poweroff or similar things to gracefully shutdown a system? Having a way to prompt the user that applications are open similar to that to Windows for example, or just automatically requesting the closing of or the sending of term or other similar signals to processes?

systemctl poweroff is considered a “graceful” shutdown. The system goes through the full, “proper” shutdown sequence, including stopping services and unmounting filesystems in an orderly manner. Processes have a chance to terminate cleanly, data is written to disk, and so on.

When you run systemctl poweroff, the system does send SIGTERM to all running processes. Each process has a chance to terminate gracefully. If a process can’t terminate within a specified timeout, it is then sent SIGKILL to forcefully terminate it.

Generally the default timeout is 90 seconds, but if you have a process that needs more time you can specify a custom TimeoutStopSec parameter under the [Service] section of the unit file. For example, to set a five-minute timeout:

[Service]
ExecStart=/path/to/your/executable
TimeoutStopSec=5min

Keep in mind, in Linux applications are often willing to immediately shut down without all the hand-wringing and “are you sure?!” that you may be used to from Windows. If you want prompts that appear asking you to save your work or whatever, depending on the application you may need to set that up yourself.

If you put together a script that handles whatever your special shutdown stuff is, you can incorporate it into systemd’s shutdown routine by putting the script in a service file and adding the Before=shutdown.target directive.

[Unit]
Description=My Really Awesome Shutdown Script
DefaultDependencies=no
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/path/to/my_really_awesome_shutdown_script.sh
RemainAfterExit=true

[Install]
WantedBy=halt.target reboot.target shutdown.target

That’s just an example obviously, but in general if a service file just runs a script it does not need to be complex.

systemctl poweroff is not a systemd unit itself; rather, it is a command that kicks off the systemd shutdown process. Essentially, running systemctl poweroff tells systemd “go ahead and start doing all the stuff you need to do before the computer shuts off, and then shut it off.”

As for modifying service files, in general it is fine if you want to make a change. In fact, systemd makes it fairly easy to do by using a drop-in system; essentially, you can make “edits” to a service unit without modifying the original unit files. Your special modifications are kept in a separate file that systemd will honor when it is running that service. If you want to learn more about that, take a look at this article here: https://wiki.archlinux.org/title/Systemd#Drop-in_files

2 Likes