The shutdown
program on a modern systemd-based Linux system
Historically, shutdown
has been a
distinct binary. All of the waiting for the shutdown time, the
wall
notifications, and setting up a nologin
file shortly before
shutdown were handled by it, internally; only at the end, when it
was time to do whatever, did it turn to the init system to cause
the actual reboot, power off, or shutdown. It followed that you
could determine whether or not a shutdown operation was (slowly)
in progress by looking for a running shutdown
command (and figure
out when it was going to happen by inspecting the command line
arguments), which is handy if you have a bunch of machines to reboot
and you're not sure you started a shutdown on a particular one.
(If you have a mass of machines to reboot on schedule for some
reason,
you obviously don't want to open up a mass of terminal windows, ssh
in to each machine, run a shutdown
command, and let the window
sit. Instead you're going to use some sort of mass action system to start shutdown
commands on each of
them. Which raises the question of whether you really did get all
of the machines or not.)
On modern systemd systems, things no longer work this way. Instead
of doing the work itself, shutdown
is now another name for
systemctl
(really, it's just a symlink) and it works by telling
systemd to do all the work. When you run shutdown
, it now just
tells you that a reboot or whatever has been scheduled and then
exits immediately. This raises the obvious question: how do you
find out if a systemd-based system has a shutdown pending?
Well, it depends on the version of systemd that you're using, because
systemd has had at least two generations of how it does this. On
the older generation, this is implemented by a systemd service,
systemd-shutdownd.service
(aka systemd-shutdownd
), the 'Delayed Shutdown Service'. If
systemctl status
reports that this service is active (or there's
a systemd-shutdownd
process running), I believe that you have a
shutdown or some other operation in progress. According to this
Stackexchange answer, you
can also see the shutdown time and so on with 'systemctl status
'.
On the newer generation, this feature has been moved into systemd's
logind
instead of being a standalone service and binary, and of
course everything is now done over DBus. There are two ways to see
the status of a shutdown (including whether or not there is one).
First, you can look for /run/systemd/shutdown/scheduled
, which
records this information:
USEC=1477000800000000 WARN_WALL=1 MODE=reboot WALL_MESSAGE=rebooting to apply crucial security updates
Second, you can ask logind for this information over DBus. Using the information from this article:
qdbus --literal --system org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.DBus.Properties.Get org.freedesktop.login1.Manager ScheduledShutdown
(I prefer using /run/systemd/shutdown/scheduled
on the grounds
that it seems a lot simpler.)
See this Stackexchange answer for a bit more details about the code involved and so on.
So, when did systemd shift from one generation to the other of this feature? I'm glad you asked. The short answer appears to be 'in systemd 220' (based on here, with git commits of eg this first one and this one). Red Hat Enterprise 7 and thus CentOS 7 have systemd 219, with the old systemd-shutdownd approach. Ubuntu 16.04 LTS has systemd 229 and uses the new approach, which is convenient for us since we have a steadily increasing number of 16.04 machines.
(I find the new approach to be more convenient because it gives me a flat file that I can look at.)
The modern new logind-based approach does make a certain amount of
wall
-style broadcast messages as the reboot time approaches, but
based on one comparative run it doesn't seem to give quite as many
messages or quite as frequently. There is a table of minutes-to-go
that logind announces at in the source code; the current list is
that logind announces at 180, 150, 130, 100, 70, 55, 40, 25, and
10 minutes, and then every minute until the shutdown time arrives.
(Currently you can see this in the when_wall
function in
src/login/logind-utmp.c.)
(This is one of the blog entries I write partly so that I can find all of this later, because I'm know I'm going to need it again. And it's only going to become more useful as we upgrade more machines from earlier Ubuntu LTS versions to Ubuntu 16.04.)
|
|