This is actually quite a difficult problem. One of the major difficulties is that the places where one most often wants to do this are the places where it's quite likely that one will be in the middle of installing or changing stuff. Another is that there's a subtle but very important difference between the system management toolset that is installed, the system management toolset that is running right now, and the system management toolset that will run at next boot.
Determining what is installed one does with a package manager, of course. But this is complicated by the fact that several systems can be installed side by side.
On Debian Linux, for example, one can install the systemd package, but it is the installation of the separate systemd-sysv package that makes it the active system. The intention is that the systemd and sysvinit packages can be installed simultaneously. Indeed, the Debian Linux crowd has taken steps in Debian 8 to shift towards every program having a different name (
/sbin/system-manager, and so forth) for this very reason, that the "non-activating" packages don't conflict on the name
/sbin/init is then a symbolic link to whichever was configured to run at next boot by an "activating package".
Determining what is running now and ready to run next one can only do with a series of toolset-specific tests, with varying degrees of risk from false positives, and with varying degrees of documentation. To check for what system manager is running right now, specifically, one really has to look at the process list or at the various APIs that system managers publish. But this isn't wholly without pitfalls.
Let's start with things that definitely will not work.
/proc/1/exe will point to the same
/sbin/init when either upstart or System 5
init are running right now. And on some systems, it's also
/sbin/init when systemd is running.
The Debian Linux crowd wanted to shift towards every program having a different name, as mentioned earlier. But this is Debian-specific, far from universal, and doesn't really help when the program is invoked as
/sbin/init (by the initramfs phase of the bootstrap) anyway. Only Felix von Leitner's minit is actually packaged by Debian 8 to be invoked with its own name.
- The existence of the control API file
/dev/initctl isn't specific to System 5
init. systemd has a (non process #1)
systemd-initctl server that serves this. Joachim Nilsson's
finit serves it too. (Just to make things extra fun, on Debian it's now located at
/run/initctl. See https://superuser.com/a/888936/38062 for details.)
- systemd, upstart, System 5
rc, and OpenRC all process
/etc/init.d/, for backwards compatibility in the case of the former two. Its existence does not indicate the presence of any given system.
Detecting System 5
Ironically, as explained at https://unix.stackexchange.com/a/196197/5132 , one way on Debian Linux at least for detecting the absence of System 5
init is the absence of
- This is an side-effect of Debian's way of packaging things like
- One part of the overall problem is that
/etc/inittab sticks around if System 5
init was used at any point in the past, because uninstalling the package does not delete its configuration file. (This has been a sizeable problem for Debian 8 work, since there are several packages in Debian 7 which install themselves by adding entries to
- It's an inverted test.
To check for systemd as the running system manager in the "official" manner, one checks for the existence of
/run/systemd/system. This is a directory, in
/run, that systemd itself creates at boot, and that other system managers are unlikely to create.
But that's merely unlikely. This check is already broken, because uselessd creates this directory too.
Other, unofficial, checks won't work:
- systemd publishes a whole RPC API over D-Bus, which even contains a version name and number; but:
- The existence of
/run/systemd/private is similarly not guaranteed and similarly duplicated by uselessd.
system-manager in nosh creates a
/run/system-manager directory. But this shares the weaknesses of the equivalent systemd check.
- The nosh
system-manager by design doesn't create pipes or sockets in the filesystem, and doesn't have an RPC API in the first place.
- The nosh
service-manager conventionally has an API socket at
/run/service-manager/control, but one can run the nosh service manager under some other system manager; so this doesn't tell one what system manager is running as process #1. In any case, it doesn't set that name itself; whatever invoked it does.
- The existence of a nosh version string, emitted by
systemctl version (if one has the systemd compatibility shims installed) and
initctl version (if one has the upstart compatibility shims installed) only indicates the presence of the toolset, as these tools make no query of the running system.
initctl makes an API call over D-Bus, and the official check is to both check that one can run
initctl and that its output contains the string "upstart" somewhere.
But, like the systemd API:
- There's no guarantee that the API will be around tomorrow or not changed at whim.
- There's no guarantee that some compatibility shim doesn't exist or won't exist in the future.
Indeed, there already is one compatibility shim. nosh has an upstart compatibility package that provides shims for the upstart
status commands. Luckily (although this was intentional), the
initctl shim does not emit the word "upstart".
root ~ #initctl version
nosh version 1.14
root ~ #