How to find out if a system uses SysV, Upstart or Systemd initsystem
The init process is always assigned PID 1. The /proc
filesystem provides a way to obtain the path to an executable given a PID.
In other words:
nathan@nathan-desktop:~$ sudo stat /proc/1/exe
File: '/proc/1/exe' -> '/sbin/upstart'
As you can see, the init process on my Ubuntu 14.10 box is Upstart. Ubuntu 15.04 uses systemd, so running that command instead yields:
nathan@nathan-gnome:~$ sudo stat /proc/1/exe
File: '/proc/1/exe' -> '/lib/systemd/systemd'
If the system you're on gives /sbin/init
as a result, then you'll want to try statting that file:
nathan@nathan-gnome:~$ sudo stat /proc/1/exe
File: '/proc/1/exe' -> '/sbin/init'
nathan@nathan-gnome:~$ stat /sbin/init
File: ‘/sbin/init’ -> ‘/lib/systemd/systemd’
You can also execute it to find out more:
[user@centos ~]$ /sbin/init --version
init (upstart 0.6.5)
Copyright (C) 2010 Canonical Ltd.
You can poke around the system to find indicators. One way is to check for the existence of three directories:
/usr/lib/systemd
tells you you're on a systemd based system./usr/share/upstart
is a pretty good indicator that you're on an Upstart-based system./etc/init.d
tells you the box has SysV init in its history
The thing is, these are heuristics that must be considered together, possibly with other data, not certain indicators by themselves. The Ubuntu 14.10 box I'm looking at right now has all three directories. Why? Because Ubuntu just switched to systemd from Upstart in that version, but keeps Upstart and SysV init for backwards compatibility.
In the end, I think the best answer is "experience." You will see that you have logged into a CentOS 7 box and know that it's systemd. How do you learn this? Playing around, RTFMing, etc. The same way you gain all experience.
I realize this is not a very satisfactory answer, but that's what happens when there is fragmentation in the market, creating nonstandard designs. It's like asking how you know whether ls
accepts -C
, or --color
, or doesn't do color output at all. Again, the answer is "experience."
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 (/lib/sysvinit/init
, /lib/systemd/systemd
, /sbin/runit-init
, /sbin/minit
, /sbin/system-manager
, and so forth) for this very reason, that the "non-activating" packages don't conflict on the name /sbin/init
. /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.
General non-starters
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 5init
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 5init
. systemd has a (non process #1)systemd-initctl
server that serves this. Joachim Nilsson'sfinit
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 init
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 /etc/inittab
. However:
- This is an side-effect of Debian's way of packaging things like
/etc/inittab
. - One part of the overall problem is that
/etc/inittab
sticks around if System 5init
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/etc/inittab
.) - It's an inverted test.
Detecting systemd
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:
- This is not covered by the infamous "Interface Stability Guarantee" and could change tomorrow or at whim.
- So too does the lookalike D-Bus server in systemd-shim.
- So too does uselessd.
- The existence of
/run/systemd/private
is similarly not guaranteed and similarly duplicated by uselessd.
Detecting nosh
The system-manager
in nosh creates a /run/system-manager
directory. But this shares the weaknesses of the equivalent systemd check.
Further non-starters:
- 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
system-control version
,systemctl version
(if one has the systemd compatibility shims installed) andinitctl 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.
Detecting upstart
Upstart's own 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
initctl
,start
,stop
, andstatus
commands. Luckily (although this was intentional), theinitctl
shim does not emit the word "upstart".root ~ #initctl version nosh version 1.14 root ~ #