Much have been said throughout recent years regarding Unix and Unix-like init (initialization) systems. It became the subject of a heated debate once a particular init system was proposed, and certainly more so during its rise to power, over the last 7 years.
That system turned many Unix and alike systems, i.e. Linuxs and BSDs, upside down, touching and interfering both individuals and businesses, forcing many out of their comfort zone and into the (then perceived) abyss.
However, 7 years after Systemd’s release, much of the fog surrounding it has cleared up, precipitation have mostly sank, those who had things to say have already said what’s on their mind and those who wanted to take action have already took it.
Without even realizing it perhaps, we have now all slipped through into a new era, where Linux operating systems are more unified and distinct from non-Linux OSs than ever before.
Facing this newly created reality, where most of the major Linux distributions had already decided to embrace Systemd, including: Fedora, Debian, Ubuntu and Arch among many others, it appears we are now left with two main schools of thought, at least as far as PID 1 is being the subject of concern.
- On the one hand, we have the younger, vibrant, thinking big, Systemd which although being a newer project is in fact the larger, more dominant init* at the moment. This is where most of the mainstream busyness lies at nowadays.
- On the other hand though, we have the older, also vibrant, smaller in scale, openRC which is mostly maintained and developed by Gnetoo devs (although contributors could be of any other faction or denomination: distributions or individuals). This is the current init crown contender which might be considered conservative, old-school and perhaps the underdog in this comparison.
* Actually, Systemd is much more than simply an init program, but you’ll find out more about it later in the article.
Despite not being mentioned, there are of course a few other init systems out there (runit, upstart, s6, system XVI comes to mind), some of which may cater to a very specific niche while others might aim at a more general purpose. With no intention to discredit or disregard the importance of each of these projects, it appears however, that openRC is the most widespread of them all as well as the closest to feature-parity with Systemd of the bunch.
Furthermore, most of the init alternatives are currently found at the very margins of Linux ecosystem, even openRC is quite marginalized when you look at the entire Linux ecosystem as a whole, so definitely, the rest of init replacements are at the margins too and thus, far from constituting a significant opponent to Systemd and thereof were not considered in this comparison.
Also before we begin, I’d like to acknowledge that just as you, I’m also a human-being, prone to mistakes, biases and what-have-you. I did tried my best to stay objective throughout the comparison, sticking to facts, for the benefit of the greater good, that is. However I’m not free of flaws, so if you find any mistakes or find yourself having reservations regarding what you’ve read, please feel free to share it with the rest of us through the comment section, make us all more knowledgeable and informed.
With that said, the purpose of this comparison is not to please everyone by echoing the sayings of proponents from each side. The purpose is to reach the underline truth about the inits, help those who need / want to make clear cut decision regarding their system to be able to do so based on facts and not merely random sentiment.
I do have one request nonetheless in case you decide to comment, please try to avoid any derogatory form of speech and stick to constructive criticism. The fact you’re sitting next to a keyboard, perhaps on the other side of the world, does not mean you need to let loose any sense of dignity or civilized manners. “Decency before advocacy” as we say here.
About the Comparison
The comparison before you is the fruit of labor of sifting through many online resources (you’ll find a list of those mentioned at the bottom of the article), digging data even from the darkest corners of the Internet, closely examining each source, not only by content but also by the general notion / ideology authors may have held through their writings. Summing up all those sources and forming a greater picture out of them, and yet as part of these resources were clearly leaning towards one side or the other, every piece of given information was closely examined and verified thereafter.
At the end of the day however, the most crucial role in forming this comparison, I attribute to physical experiments (on physical hardware as opposed to virtual) which I personally held. Not relying solely on other peoples’ opinions / claims but testing and in some cases even reviewing available source code were eventually the key factors assisting me in reaching the conclusions you’re about to read.
If you feel uncertain about one or more of the points raised in here, by all means, do the same as I did, test and verify it for yourself, I implore you.
Table of Contents
- The Essence of Init
- Two Dominant Approaches
- Natural Evolution
- A Battle of Ideologies
- Dry Facts
- Examining the Facts
The Essence of Init
Init, as pointed at the beginning of the article, is short for initialization. It was apparently called that way because its original purpose was to initialize relevant processes during boot time.
When you think about it, every time you turn on your computer and boot into your – graphical desktop, server environment, work station, etc – there are quite a few tasks you must run in order to have the basic functionality of your system.
For instance, you may need to mount file-systems, start a network manager (so you could connect online), start a sound server and so on and so forth.
It would be somewhat bothersome, by who ever designed your operating system, to ask you to issue commands that would start all the tasks mentioned above and more, every-time you boot your system.
Therefore, the init process which is the first process to run right after the kernel has finished loading, is there to automate things for you.
Init is hence the first process to run and thus it commonly receives the process identifier of 1 (PID 1).
Being the first running process which starts all those other processes you may run, init is put in position of great power, as it gets the privilege not only to be able to start each of the processes it starts but also to stop, restart or do other things with these processes.
The great power in the hands of init makes it one of the most important (if not the most important) programs on your system.
Two Dominant Approaches
The origins of contemporary init which led to the point where we are today started long before Systemd or openRC came to be. In fact, it even started long before there was a Linux operating system or kernel.
Our first piece of relevant history starts at the early days of Unix with “Research Unix-style/BSD-style” init system. That system used a centralized file (located in /etc/rc) to determine what programs will be run by init.
Later in time, perhaps due to the need of reducing risk by editing such a significant file, BSD style init evolved to also support /etc/rc.local file which is run at the end of the initialization sequence, in addition to /etc/rc.
Further ahead, BSD style init has evolved even more into what most of the BSDs (and a number of Linux distros) use nowadays which is a /etc/rc.d directory that uses explicit dependency tags placed within each script inside that directory to determine the order in which scripts (services) are executed.
Therefore we can say that BSD-style is a dependency-based init.
In contrast, there was another init system which was introduced at a bit later point in time, bearing the name SysV-style init, or simply sysV.
sysV brought a new concept to the Unix world called runlevels. runlevels basically constitute a state of the operating system in which the user might be interested in being in at a certain moment in time.
For instance, when booting into no-network state, there probably won’t be any need to run certain scripts which concern networking, or when switching to shut down state, there are certain scripts that need be run while others would surely be unnecessary. runlevels are thus making sure that certain scripts would be initialized only when the system is found at the corresponding state.
Hence we can say that sysV is a state-based init.
At this point you might ask yourself: “sysV? BSD? where’s the connection to openRC and Systemd?” and the answer is – natural evolution.
The keen sighted among you have probably noticed there’s a common denominator between /etc/rc (used by BSD init) and the letters RC in openRC. This is no coincidence. openRC was created by a NetBSD developer who started the Gentoo/FreeBSD project. Gentoo’s flagship feature – Portage package manager – was also inspired by a BSD operating system (FreeBSD’s port system), therefore it is no surprise Gentoo was quick to adopt openRC.
Basically, what openRC did initially was to bring BSD-style dependency-based initialization and merge it with the state-based feature of sysV, so openRC became both state-based and dependency-based init.
openRC runlevels: services enabled [left] on certain runlevels
Now, many don’t know this actually but up until a few months ago (April, 2017), openRC wasn’t a fully fledged init system on it’s own, on the contrary, by default it actually hooks into the current running init system (be it on BSD or Linux OS) and add to it the features of runlevels and dependency initialization.
However, as of version 0.25 openRC can also replace the current init system on Linux distributions, although it is not configured to do so by default.
So we now know the basics of how we got to the point where openRC came to be, but what about Systemd? Systemd, as mentioned earlier, came only at a later point in time. It too can be viewed as part of the natural evolution process init systems went through, however Systemd as you’re about to find out is much more than just a mere step in evolution, rather it is a step forward and a change of direction at the same time, which probably is why it became the subject of so many controversies in recent years.
Starting with the evolution side, Systemd came into the fore in a time where most Linux distros still used plain sysV init with a few modifications here and there. Certainly, in a time where everything on your system is way more dynamic than it used to be – different devices are being plugged in and out, different networks can be switched back and forth, etc, the basic concept of static runlevels (sysV incorporated up to 10 numbered runlevels) is no longer sufficient.
Systemd basically saw that growing trend and decided to tackle it head-on. Creating dynamic states (as opposed to runlevels’ static states) it allows for arbitrary runlevels names and grouping/chaining of different runlevels according to a specific use-case, all that by utilizing a set of editable “target” files (end with the suffix .target) to determine which services should be run upon the initialization of a certain state.
So in practice, Systemd has renamed runlevels as targets, made them be more flexible by allowing arbitrary naming and removing the limit of how many can be present, and allowed for interdependence between different targets e.g. booting into graphical user mode (desktop) also may invoke the initialization of multi-user mode and other modes as well.
It’s important to mention at this point that openRC have basically implemented the same functionality, through incorporating internal and user-defined runlevels and via adding stacked runlevels capabilities, i.e. abilities to group runlevels together. Albeit seemingly implemented as an afterthought, these features are pretty simple to use and work quite well – for example, adding a stacked runlevel simply require creating a new directory while creating a new target require both creating a new target file and editing its content.
Furthermore, in order not to break backwards compatibility, openRC implements these features on top of the existing sysV/BSD-style features, so no need to change any of your work-flow.
The final result is that we now have a dynamic state-based and dependency-based init systems that are capable of handling current user needs and are more fitted to modern times use cases. This forms the last link of natural evolution in the init design chain for now.
A Battle of Ideologies
So far for the natural evolution of init systems, however Systemd did not only make a quantum leap in evolution. As mentioned in the previous section, it also embarked upon a different path.
You see, there’s a good reason for why Linux is being referred to as a Unix-like operating system although not being a descendant of Unix (not sharing source code) at all. The reason is that it basically adheres to the Unix philosophy and principles. These are a set of well established rules and precepts, that have proven to surpass the test of time, which many people believe is a key part of what makes it so successful.
Some of these principles stresses the importance of portability and modularity (“Choose portability over efficiency”, Rule of Diversity, Rule of Modularity) others, emphasize simplicity and minimalism (Rule of Simplicity, “Small is beautiful” and also Rule of Parsimony) and perhaps the most known principle, commonly identified with Unix, is the ‘do one thing and do it well’ or as originally phrased “Make each program do one thing well”.
Now, when you take a close look at each of our herein compared init systems, we have openRC on the one hand which adheres to all the principles mentioned above and more –
- openRC is portable: it can work on BSDs as well as Linux distros.
- openRC is modular: it allows to replace parts of the program with other pieces of software (the basic init part itself can be replaced by sysV or BSD-style init).
- openRC certainly is doing one thing and doing it well: it focuses on being an init system and nothing beyond that.
- openRC is minimal: its aim to do only one thing keeps it generally small in size.
- openRC is simple: it can be broken into smaller pieces of code, its (relatively) small size and focus on doing one thing well makes it quite simple.
On the other hand however, we have Systemd which appears to be breaking all of the above mentioned principles and possibly a few more along the way –
- Systemd isn’t portable: it is meant to work on Linux and Linux only.
- Systemd isn’t modular: although it can be theoretically broken into separate modules, i.e. journald, logind, networkd, etc… the modules in Systemd are tightly integrated. They are all shipped together with Systemd and can’t be easily removed/replaced.
- Systemd isn’t doing one thing and doing it well: integrating quite a few additional components as part of its basic functionalities (e.g. timedated, logind, networkd, etc) and with the intentions of expanding in the future, Systemd certainly isn’t focusing on doing one thing and doing it well.
- Systemd isn’t minimal: Systemd incorporates multiple tools into one program which certainly prevents it of being called minimal.
- Systemd isn’t simple: due to it’s tight modules integration it’s harder to break Systemd into a finite smaller pieces. From the user perspective, a notable example would be journald binary logs – not only are they require a specific tool to be read (journalctl, can’t be read as plain text) but also the default output encompasses a wide range of different events (not just init related) which makes harder to read.
Systemd: listing units
Nonetheless, despite the utter disregard of some of Unix’s proven good practices, Systemd does have its ideological merits. The monolithic approach (meaning incorporating all the different tools into one program) which Systemd advocates, is geared towards performance and has also proven to be quite successful, especially in the context of Linux, where Linux itself is designed as a monolithic kernel.
It is hence no wonder that Linus Torvadls, founder of the Linux kernel, was once quoted saying:
“I don’t actually have any particularly strong opinions on systemd itself. I’ve had issues with some of the core developers that I think are much too cavalier about bugs and compatibility, and I think some of the design details are insane (I dislike the binary logs, for example), but those are details, not big issues.”
As you can probably realize by now, more than it’s a clash between two distinct init systems, the clash between openRC and Systemd is also a clash of different philosophies.
This article compares and contrasts init systems. While most of the init systems compared below are available for Gentoo, some (like launchd and SMF) are not.
|Supported in Gentoo||partially (used by OpenRC)||Yes (default init)||No||Yes||No||No||Yes||No||Yes||No|
|Package / Bug#||sys-apps/sysvinit||sys-apps/openrc||bug #498376|
sys-apps/upstart in unity-gentoo overlay.
|Supported platforms||Linux / BSD||Linux + BSD||Linux||Linux||Solaris||MacOSX||Linux||Linux||Linux||BSD|
|Main coding language||C||POSIX shell (+ C)||C||C||C||C||C||C||C||POSIX shell (+ C)|
|Main dependencies||-||init (sysv or BSD)||D-Bus||D-Bus||init(sysv?)||-||libc, /bin/sh||?||-||rcorder|
|Init script/service format||single config file||shell scripts||config files + shell fragments||config files (ini)||XML (+ shell scripts)||plist||multiple or single .conf||multiple or single .conf||shell scripts||shell scripts|
|Per-service configuration||No||Yes (conf.d)||With in-job mechanisms (normal exit, respawn)||Yes||?||?||Yes (v1.1+)||?||No||No|
|Running as a daemon||Yes (PID 1)||Yes (PID 1)||Yes (PID 1)||Yes (PID 1)||Yes (invoked)||Yes (PID 1)||Yes (PID 1)||Yes (PID 1)||Yes (PID 1)||Yes (PID 1)|
|Cross-service dependencies/events||No||Yes||Yes||Yes||Yes||No||Yes (basic support, v1.3+)||?||Yes||Yes|
|Parallel service startup||Yes||Yes (optional)||Yes||Yes||Yes||Yes||No||Yes||Yes||Yes|
|Keeping daemons alive||Yes||Yes (optional v0.21+ via supervise-daemon)||Yes||Yes||Yes||Yes||Yes||Yes||Yes||Yes|
|Preferred service file supplier||n/a||Gentoo||Ubuntu||upstream||Solaris||MacOSX||n/a||n/a||Void Linux||NetBSD, FreeBSD, OpenBSD|
|License||GPL v2+||2-cl. BSD||GPL v2||LGPL v2.1+||?||Apache License 2.0||Unlicense||MIT||BSD||BSD|
Supported services (in Gentoo)
|Filesystem mounting||One script per group (root, local, network, swap...).||Two units per mountpoint (fsck + mount), runtime-generated with dependencies.|
|getty (terminal prompts)||Started through /etc/inittab.||One unit per console, instantiated from template on-demand.|
|Networking setup||Several options like dhcpcd netifrc or NetworkManager.||External (NetworkManager, networkd, DHCP daemons).|
|X11 Display Manager setup||Single service for all (required to auto-restart).||Separate DM units.|
- Runit — a daemontools-inspired process supervision suite that also provides a program suitable for running as process 1
- s6 and s6-rc-based init system — an init system built using components from the s6 and s6-rc packages
- nosh — a multi-purpose init and process supervision software package made by Jonathan de Boyne Pollard.
- OpenRC — a dependency-based init system that maintains compatibility with the system provided init program (see the init section).