How can I give a grace period to CTRL-ALT-DEL in systemd
Solution 1:
In systemd, the CTRL-ALT-DEL key sequence triggers the ctrl-alt-del.target
(which by default lives in the system path, /lib/systemd/system/ctrl-alt-del.target
on Debian) and starts the systemd-reboot.service
. It can be overridden by creating a local version, /etc/systemd/system/ctrl-alt-del.target
. Creating it as an empty file effectively disables the key sequence.
One way to schedule the reboot in the future would be to have this target require a service (ex local-delayed-reboot.service
- create the file in the same directory) and have this service configured as oneshot with ExecStart=shutdown -r <delay>
.
What bugs me in this method is that we're going all over the place, ctrl-alt-del trigger a systemd service which calls a binary which send a dbus message back to systemd to schedule the shutdown (logind handles it...). I though it might be cleaner to actually keep starting the same target but only after executing a systemd timer. This is how I implemented it:
Create a warning service - this is to warn (using wall
+ tee console in case no one is logged in) that the reboot is going to happen. adjust the message - esp. the delay - as desired:
/etc/systemd/system/local-delay-reboot-warn.service
[Unit]
Description=Reboot Warning
[Service]
Type=oneshot
ExecStart=/bin/sh -c '/bin/echo -e "\aCTRL-ALT-DEL has been hit! Reboot in 60 seconds...\n\nTo abort:\n systemctl stop ctrl-alt-del.target"|tee /dev/console|/usr/bin/wall'
Create a timer that starts the shutdown unit after specified time - the timer depends on the warning service so warning message is fired first (likewise, update the delay as desired):
/etc/systemd/system/local-delay-reboot.timer
[Unit]
Description=Reboot delay
DefaultDependencies=no
# Warn first...
Requires=local-delay-reboot-warn.service
After=local-delay-reboot-warn.service
# Make this timer stop if ctrl-alt-del.target is stopped
PartOf=ctrl-alt-del.target
[Timer]
OnActiveSec=60s
RemainAfterElapse=no
Unit=systemd-reboot.service
# Disable systemd's timer optimisations
AccuracySec=1us
[Install]
WantedBy=ctrl-alt-del.target
Finally override ctrl-alt-del.target
with this:
/etc/systemd/system/ctrl-alt-del.target
# Custom reboot action
[Unit]
Description=Reboot (delayed)
DefaultDependencies=no
Requires=local-delay-reboot-warn.service local-delay-reboot.timer
After=systemd-reboot.service
AllowIsolate=yes
JobTimeoutSec=30min
JobTimeoutAction=reboot-force
[Install]
Alias=ctrl-alt-del.target
After all I'm not sure it was really worth it but it was definitively educational in understanding how to use timers.