Block systemd-initiated poweroff/reboot/halt until configurable condition checks pass
- Python 2.7
- systemd
- Can be launched from a simple systemd service or run manually
-
Download and execute
rguard
without any condition checks to confirm it really can block shutdown.[root]# cd /usr/sbin [root]# curl -kO https://raw.githubusercontent.com/ryran/reboot-guard/master/rguard % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 16575 100 16575 0 0 54536 0 --:--:-- --:--:-- --:--:-- 54702 [root]# ll rguard -rwxr-xr-x. 1 root root 16575 Sep 1 02:46 rguard [root]# rguard -1 WARNING: ☹ Blocked poweroff.target WARNING: ☹ Blocked reboot.target WARNING: ☹ Blocked halt.target [root]#
-
Try to reboot/shutdown/halt and fail. Note that the old legacy commands (
halt
,shutdown
,reboot
) trigger wall messages regardless.[root]# systemctl reboot Failed to issue method call: Operation refused, unit reboot.target may be requested by dependency only. [root]# shutdown -h now Failed to issue method call: Operation refused, unit poweroff.target may be requested by dependency only. Broadcast message from root@localhost on pts/0 (Mon 2015-08-31 02:28:05 EDT): The system is going down for power-off NOW! [root]#
-
Disable the blocks.
[root]# rguard -0 WARNING: ☻ Unblocked poweroff.target WARNING: ☻ Unblocked reboot.target WARNING: ☻ Unblocked halt.target [root]#
-
Execute
rguard
with a tiny sleep-interval and 2 simple checks.[root]# rguard --interval 15 --unit atd --require-file /run/.require & [1] 23317 WARNING: ☹ Failed a condition-check WARNING: ☹ Blocked poweroff.target WARNING: ☹ Blocked reboot.target WARNING: ☹ Blocked halt.target [root]#
-
The conditions we set meant shutdown will be blocked while atd is active and while
/run/.require
does not exist, so fix that andrguard
will immediately unblock shutdown.[root]# systemctl is-active atd active [root]# systemctl stop atd [root]# touch /run/.require WARNING: ☻ Passed all condition-checks WARNING: ☻ Unblocked poweroff.target WARNING: ☻ Unblocked reboot.target WARNING: ☻ Unblocked halt.target [root]# fg rguard --interval 15 --unit atd --require-file /run/.require ^C WARNING: Gracefully exiting due to receipt of signal 2
- Install the latest rpm from Releases or setup yum repo:
yum/dnf install http://people.redhat.com/rsawhill/rpms/latest-rsawaroha-release.rpm
yum/dnf install reboot-guard
- If you want the service to always block reboot/shutdown, requiring the service to be manually stopped or killed, simply run
systemctl daemon-reload; systemctl enable rguard --now
and you are done; otherwise, continue to next step - Play with the options until you get them how you want them (see help page:
rguard --help
) - Copy
/usr/lib/systemd/system/rguard.service
to/etc/systemd/system
and set theExecStart=
directive to your liking - Run:
systemctl daemon-reload; systemctl enable rguard --now
- Check
systemctl status rguard -n50
or usejournalctl -fu rguard
to keep an eye on logs (turn up the--loglevel
if necesary) - Tweak
rguard.service
as required, and then re-runsystemctl daemon-reload; systemctl restart rguard
- Give feedback by posting to the Issue Tracker
usage: rguard [-1 | -0] [-f FILE] [-F FILE] [-u UNIT] [-c CMD] [-a ARGS]
[-r COMMAND] [-h] [-i SEC] [-n] [-x]
[-v {debug,info,warning,error}] [-t]
Block systemd-initiated shutdown until configurable condition checks pass
SET AND QUIT:
Execute a single action with no condition checks.
-1, --install-guard Install reboot-guard and immediately exit
-0, --remove-guard Remove reboot-guard (if present) and immediately exit
CONFIGURE CONDITIONS:
Establish what condition checks must pass to allow shutdown.
Each option may be specified multiple times.
-f, --forbid-file FILE
Prevent shutdown while FILE exists
-F, --require-file FILE
Prevent shutdown until FILE exists
-u, --unit UNIT Prevent shutdown while systemd UNIT is active
-c, --cmd CMD Prevent shutdown while CMD exactly matches at least 1
running process
-a, --args ARGS Prevent shutdown while ARGS exactly matches the full
cmd+args of at least 1 running process
-r, --run COMMAND Prevent shutdown while execution of COMMAND fails;
prefix COMMAND with '!' to prevent shutdown while
execution succeeds (MORE: Prefix COMMAND with '@' to
execute it as a shell command, e.g., to use pipes '|'
or other logic; examples: '@cmd|cmd' or '!@cmd|cmd')
GENERAL OPTIONS:
-h, --help Show this help message and exit
-i, --interval SEC Modify the sleep interval between condition checks
(default: 60 seconds)
-n, --ignore-signals Ignore the most common signals (HUP, INT, QUIT, USR1,
USR2, TERM), in which case a graceful exit requires
the next option or else SIGKILL
-x, --exit-on-pass Exit (and remove reboot-guard) the first time all
condition checks pass
-v, --loglevel {debug,info,warning,error}
Specify minimum message type to print (default:
warning)
-t, --timestamps Enable timestamps in message output (not necessary if
running as systemd service)
EXAMPLES:
As mentioned above, all of the condition-checking options can be used
multiple times. All specified checks must pass to allow shutdown.
rguard --forbid-file /shutdown/prevented/if/this/file/exists
rguard --require-file /shutdown/prevented/until/this/file/exists
rguard --cmd some-cmd-name-which-when-running-prevents-shutdown
* e.g., 'bash' or 'firefox'
rguard --args 'syndaemon -i 1.0 -t -K -R'
* Prevent shutdown if this exact cmd + args are found running
rguard --run 'ping -c2 -w1 -W1 10.0.0.1'
* Allow shutdown only if single command (ping in this case) succeeds
rguard --run '!ping -c2 -w1 -W1 10.0.0.1'
* Allow shutdown only if single command FAILS
rguard --run '!findmnt /mnt'
* Allow shutdown if nothing mounted at mountpoint
rguard --run '@some_cmd | some_other_cmd; another_cmd'
* Allow shutdown only if last cmd in shell succeeds
* When using '@', full shell syntax is supported
* e.g.: '|', '&&', '||', ';', '>', '>>', '<', etc
rguard --run '!@lsof -i:ssh | grep -q ESTABLISHED'
* Allow shutdown only if shell commands FAIL
* In this example, only if there are no established ssh connections