The shutdown program on a modern systemd-based Linux system

October 22, 2016

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.)

Written on 22 October 2016.
« The shutdown command is a relic of BSD's historical origins
I should keep a released version of the Go compiler suite »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sat Oct 22 00:19:44 2016
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.