50 comments

[ 2.8 ms ] story [ 97.2 ms ] thread
This is a great in depth article; it covers a lot and has liberal use of commands.
The irony is that all commercial UNIXes have moved beyond init for their daemon management, yet on Linux it is still highly debatable.
The debate is not in “moving beyond init”. The debate is specifically with systemd. There are many other post-init systems.
Except the other candidates never had someone put the hands into the work to the extent that systemd developers have done, so is the nature of FOSS.

Who gets the work done wins, even if it isn't the best solution.

> Except the other candidates never had someone put the hands into the work to the extent that systemd developers have done

or they haven't simply had corporate leverage of Red Hat behind them

One had corporate leverage of Canonical, and the others, well that is what FOSS is all about.

One gets what they are willing to pay for, via work or monetary contributions, otherwise just take what others have decided to make for them.

> One had corporate leverage of Canonical

Canonical has had 1/1000 of leverage of Red Hat at the time.

> systemd has long since outstripped what’s required of an init system

I think this is the fundamental disconnect.

systemd isn't an init system. It's a collection of useful programs for general running of a system, including but not limited to an init program.

I also think folks tend to underestimate just how many things you end up needing to support various init schemes.

Every single item listed under his "Some of the daemons provided by systemd are:" example is something that could have a meaningful impact to startup depending on configuration.

They happen to be useful later too, but that doesn't mean the system doesn't need them during init.

I also feel that it’s useful to take a pragmatic perspective on what an init system must cover. As someone who uses linux on the laptop, everything from boot to getting to a usable desktop is part of the “init” as far as I’m concerned. And I love the fact that there is a unified orchestration of all the necessary details (hardware devices, network connections, etc/whatever) to get me to a nice working environment fast. I don’t see what is there to complain about that!

Also, I find it strange how folks randomly get hung up on “Unix philosophy” without consistency, or regard for relevance (Per the Unix philosophy, you should not be checking email on a browser meant for webpages). It’s not like Unix is some pinnacle of system design. It was a good thing for 50 years ago, but our computers and our needs have evolved significantly since then.

Here's my hot take: systemd actually embodies the so-called "UNIX philosophy" better than any of the other alternatives.

The UNIX philosophy is theoretically "do one thing and do it well", but in practice means "create small, composable pieces which can be used together or separately to accomplish what you need."

"systemd" the project is certainly huge and all-encompassing, but you could say the same thing about GNOME, the GNU project, or even GCC itself. The systemd project, however, is divided up into a ton of smaller components, all of which are relatively easy to understand in isolation and which almost universally have clear interoperations with each other.

Case in point: systemd ships two components, systemd-networkd and systemd-resolved. I typically reconfigure my systems to use these, as I find the documentation simple to understand and the config file easy to write by hand, even from memory. Compare this to, say, netplan, which I've never actually googled a full list of options for.

That said, both of them are optional, and Ubuntu 16.04 for example used systemd in what was apparently as few places as possible, notably not using systemd-networkd or systemd-resolved. They were easy to enable and use, but they were by no means necessary.

LIkewise, systemd ships systemd-machined, a framework for creating "machines", which are containerized systems which operate like virtualized systems, with their own copy of (probably) systemd running inside.

The systemd tools, like systemctl and journalctl, can interact directly with these machines, meaning that you can use the same tools on the same command-lines to access what is effectively a "containerized" system's logs in the same way that you would locally. Likewise, systemd-networkd has configuration to automatically bring up their network configs as soon as they're created, without having to do anything manually. Again, it's not shipped by default and definitely not enabled by default.

In this way, I would say that systemd actually embodies the so-called "UNIX philosophy", by creating a bunch of separate daemons and systems, all of which can work well together but few of which are inherently required by each other. It also adds a ton of functionality which is effectively impossible to add to existing init.d systems in any maintainable way (like spawning processes in their own cgroups and namespaces, creating ephemeral users with arbitrary UIDs for those processes, creating private /tmp directories for individual services, adding bind mounts, restricting syscalls, mounting the root filesystem read only, and so on.

In essence, systemd gives you all the tools you need to build up whatever system management you want, but if you just want "execute this binary, which will not fork, and keep it running" then you can do that too, without any of those extra features getting in the way.

If systemd was written by someone with just a bit more taste in structure and APIs, I might believe you, but that just isn't the case. Why do I have to wait for several minutes to boot or reboot my machine when something goes odd with one of the services (like dns not working due to a transient network issue)? Why was ntsysv and chkconfig support (the baby) thrown out with the bathwater until almost a decade after systemd was introduced? The author has consistently demonstrated that he does not have the ability to make decisions that take into account the sysadmin / end user experience when things go awry. That's what frustrates me about systemd. At least I was able to debug the shell scripts that shipped with sysvinit. These days I have no control over that part of my machine.

Fwiw, the same disease infected gnome a long time ago as well. One day my key bindings surprisingly changed from unix to windows style in an update. Then I lost the ability to customize the widgets surrounding windows by the window manager. Control over focus follows mouse was lost... It drove me away as a user because my preferences were no longer worth supporting.

I guess I'm just turning into a grey beard at this point. Sigh.

> Why do I have to wait for several minutes to boot or reboot my machine when something goes odd with one of the services (like dns not working due to a transient network issue)?

Because one of your other services has said it depends on network.target/network-online.target and is in the critical path of your boot. Check which one with "systemd-analyze plot > plot.svg" and "systemd-analyze dot 'network.*' | dot -Tsvg >network.svg". You can also see the critical chain and which parts block faster boot with "systemd-analyze critical-chain".

I think if you stopped expecting systemd to act like something else and instead treated it like the toolkit that it is you'd see that it does what it says it does quite well. Those issues with boot you mentioned are often that the distro ships a bad systemd config for a certain program.

Why do you think systemd is defendable for this? The prior init system had a means by which individual init scripts could be disabled during boot. I can't run systemd-analyze when the system off in lala-land for 5+ minutes. Moreover, if I know what is wrong, why can't I just cancel the job it's waiting for like I could previously from the console? It is a unacceptably bad user interface experience. There is no excuse for it. Again, this worked previously - why was this functionality lost / hidden? It's this "punch the user in the face" style of user interface design that I object to that is so prevalent in the corner cases of modern UIs.
A service has been configured that to say that it won't start until the network is up. Another target, your user interface has said it depends on the previously named service.

What is the correct action for systemd to take here? After a timeout it will do what you said it will do, but until then it will try to do what the configs have said it should do.

You can tweak this however you want. You can shorten the timeout to whatever you want, you can change the dependency graph so that particular unit does not depend on the network, you can disable it completely.

> It's this "punch the user in the face" style of user interface design that I object to that is so prevalent in the corner cases of modern UIs.

I don't understand what you mean here, it was configured to do one thing, and it did that thing. You can of course say that it's a bad config (which is probably true), but then it's either the distro, the packager, systemd's defaults (which often are not ideal) or your own customizations. I'm all for arguing about better defaults in systemd and making distros better config their packages, but the actual systemd init seems to have done exactly what it was told to do here. Again, I'd like to say that distros/packages/users of systemd treat it like a pure init and often don't use it as intended.

> I can't run systemd-analyze when the system off in lala-land for 5+ minutes.

If the tree of critical services for your boot are that broken I'd assume you need to boot into single user mode or use a recovery usb. But if you actually boot after those 5min I'd expect you to easily find where those 5mins where lost using the tools I mentioned above, which is more than I can say for previous inits.

Why does login on a console terminal depend on networking being up? It's a false dependency, one decided upon by the developer of systemd. And it was a poor choice. The mindset that "it's configurable" is inexcusably lame. That mantra allows bad developers to get away with not putting in the work of thinking about and understanding how users experience their software. It also allows rewrite-the-world projects to take off and throw out all the knowledge that is implicitly present in an existing system before having understood why that complexity came to exist in the first place.

Those who do not try to understand history are doomed to repeat it. That has clearly happened in the case of systemd and is why I don't think the attitude it presents towards end users is at the level that such a core piece of infrastructure should display.

I'm guessing it wasn't the systemd developers that configured it as such, but without seeing your dependency graph and knowing your distro and installed packages I don't know.

Maybe your distro supports LDAP or another remote user directory? Maybe you just have some services installed that depend on the network and that say they are critical to the multi-user.target? You haven't given enough info for me to know, but it probably isn't systemd's fault in this case.

The distro I use is developed by the company that employs the primary systemd developer. Do you really expect me to believe your assertion that he holds no responsibility for how systemd is shipped by that distribution?
Well, if you used the tools I mentioned you'd know who/what configured your system that way and how to fix it.
> In this way, I would say that systemd actually embodies the so-called "UNIX philosophy", by creating a bunch of separate daemons and systems

I think it doesn't, because if a service isn't integrated with systemd it has little chance of being distributed with a systemd distro. And if it can't be included, why package it at all? End result: it becomes up to the user to build it from the source and do everything else (config, integration, updates) on their own.

> but in practice means "create small, composable pieces which can be used together or separately to accomplish what you need."

Except they are not composable on a package managing level. At least they weren't Debian, back when I tried.

You cannot just pick some. Update a wrong package, and the whole systemd monolith came in via dependencies, throwing out the old initd system.

Add to that the amount of new bugs that always come in when you write something new, and you have a very unpleasant experience.

Add to that the "I don't care what other people think, I do it MY way, and now you all also have to do it my way, if you want or not" attitude, and I switched to Devuan and never looked back.

Systemd has lots of goods ideas. And the existing alternatives are really sucky in places (but at least you know where they suck, can can deal with it).

If they really had written a small init system, and allowed pick-and-choose replacement of other parts, it would have been awesome. But they didn't.

The term is "middleware". It's OS middleware. It's an attempt to create a third level between "kernel" and "userspace".
I’d only ever used systemd until recently when I installed Alpine on my home server, which uses OpenRC. I appreciate OpenRC’s simplicity but I miss some of the conveniences of systemd. Overall though, I think one of systemd’s biggest advantages is the wealth of documentation and examples available for it. (Thanks, Arch wiki!)
I’ve come to appreciate the ease of creating “init scripts” with systemd, and also make regular use of the lightweight monitoring/auto-restart features. Likewise for running multiple instances of the same software.

But I do think the project suffers a bit of scope creep as it starts replacing cron, syslog, network device management, etc.

I can understand the reasons to centralize things, but I’d be happier if systemd “did one thing well” instead of trying to do it all.

Scope creep is my biggest problem with systemd. I'm not excited about the recently announced homed, for example. I'm not sure it's the right solution, nor am I sure that there is an actual problem to be solved.
I've become a big fan of systemd timers over cron jobs.

The command itself is separated out into a service with all the isolation and journalling features of a service.

You're able to test the command and know 100% it will run with the exact same environment.

You can choose to disable a timer and invoke the service manually.

You can setup alternate or multiple timers for the same call.

It supports all the timing options of cron and expands them.

You can explicitly state cron job ordering and dependencies. I've seen too many systems where the system is only fully up after several @reboot cron jobs start in some unspecified order.

Don't worry about syslog going anywhere. Journald's scope is defined at providing journalling for standard out and standard error of services. In the past this output was typically sent to /dev/null or a custom log file and if you didn't bother to specify then maybe your system would be configured to send throw it away or pipe it to a file or send it to syslog.

With systemd/journald, it is collecting only standard out and standard error. It holds it in a rotating journal, and then forwards everything to syslog for any actual log management and persistence.

> With our happy-go-lucky metric, systemd comes out at about 5 percent the size of the kernel, which is crazy!

I'm curious why the author feels that's crazy. Also the justification for the count is super weak.

Linux 5.6.19 kernel is ~25 million (25195258) lines of source in .c, .h, & .cpp files. Systemd is ~603k (603054) lines of code in .c, .h, & .cpp files.

That already halves the ratio. I'm sure if you

What you really want is number of lines of code compiled into user-facing artifacts. The rest is all support tools, build scripts, tests, etc etc. That isn't relevant when people are comparing "complexity" of the project. If the project has a lot better unit test coverage that doesn't make it "more complex". Same goes for documentation. It just means its more thoroughly tested or better documented (systemd looks like it has another ~50k lines of code that are in files with the word "test" in it).

It certainly sounds crazy, compared to the maybe 10KB of init.d scripts on a typical older Unix system.

Yeah, I realize that isn't quite apples-to-apples, but still, systemd is a ridiculous beast. We used to mock Windows for this sort of thing, and now we've become them.

I think at this point, the systemd mess is an opportunity.

Write a better one.

"Be the change that you wish to see in the world."- Gandhi (maybe)

There are already better ones. The problem is more social than technical. I'm using Void Linux with runit and it's simple and functional; I've never once missed systemd. And the BSDs all manage fine without it as well.
> runit employs a concept of a service directory, responsible for an individual service, which is a process to monitor and an optional log service

Hey look at that. The critique that systemd has a log daemon (why does init need a log daemon?) doesn't really fly. Also runit doesn't have the ability as I understand it to properly specify dependencies between components falling back to the crap of runlevels. You won't see it as a user. You see it consistently & repeatedly as an OS developer/maintainer & through slow boot times. Then you have upstart which has some dependency & parallelization effort.

The fundamental architectural flip that systemd takes is, as I understand it, that each service/process starts as needed & just blocks on I/O letting the kernel manage parallelism implicitly through synchronization mechanisms that are robust & easy to maintain rather than manual config files. There's a lot of complexity here. There's name discovery & registration so that when you have a dependency on you, you automatically start whenever a dependency tries to access you. The logging mechanism is because you want to make sure that logging is robust & functional. The binary mechanism is great because it drastically shrinks the size of the log files, reduces the overhead (printf format strings are expensive), & makes it easier to write tools to process them.

I'm not sure about the DNS & other binaries but I'm sure there are similar intrinsic architectural problems those tools are solving. Again, none of these are necessarily ones you see as an end user directly. You see it indirectly because a lot of diffuse time is spent finding/fixing bugs due that architecture (yes there are still bugs but they're of a different flavor, and, hopefully, bugs you'd have in either system.

BTW when I last looked at systemd, superficially it looked very very similar to launchctl in terms of design with many of the same benefits.

It's not that trivial to "write a better one" while broadly keeping the behavior and desirable features that systemd proponents have come to want. It will have to happen at some point, because the sheer amount of incidental complexity in systemd is quite unsustainable - but a lot of hard, fundamental work will be necessary.
Considering the functionality systemd provides shouldn't we include the line counts for dnsmasq, syslog-ng, netctl, dhcpcd, podman, cronie, dbus-broker, supervisor and a few others too?

I get that not all people want to use the whole systemd family of tools, but comparing line counts like this is ridiculous and unproductive.

So wait. You're saying a 5x increase in the amount of code that solves in a broader range of problems than just those init scripts, that doesn't seem ridiculous to me. What's the size of just the initd piece? Systemd is also significantly faster than the old init.d scripts to boot. Not sure how well it outperforms upstart & haven't been able to find those details.
My math says 60x increase, which is a lot considering that the liability of each added source line is superlinear.

And it's also a lot considering that most (?) of those lines of source are compiled into a single inscrutable binary. One of the great boons of init.d shell scripts is that you can just look at them when something is going wrong, and quickly realize that they have a bug.

If something's wrong with a unit file (and/or systemd itself) it can be extremely difficult to debug. The unit file for a reasonably common piece of software (ganglia) is broken, and apparently still is after years. I've no real idea of how to debug this, and certainly don't have time to fuck with it. At least in this regard, systemd sucks.

Whoops. My bad with the math. systemd is a bunch of purpose-built libraries though so I don't follow your reasoning. In fact, by comparison you should have more of a problem with the Linux kernel - 28 million lines of code in largely a single executable.

The init binary of systemd itself is ~70k if my math is correct & still has a much richer feature set.

I don't know what init.d shell scripts you've been looking at but my experience has not been as pleasant. Also, if you as an end user are looking at init scripts there's something massively wrong with the init system. Never heard of Ganglia but they seem to be on github. Have you filed a ticket with them? Have you messaged them on whatever forum/IRC the devs hang out on with your issue?

There's a good reason why the kernel is a single "binary". It's far less clear why the init system needs to be, especially since it wasn't for decades.

Yeah, I'm not crazy about the various init scripts that have been produced over the years. But at least when they're broken, I can usually just glance at them and see that. With systemd, mostly one just gives up.

I dunno, I like systemd. I do not need to close file handles in my daemons anymore.
Assuming it's supported, I also don't need to open sockets in my daemons anymore. Now I can run services on port 443 which are never root at any point.
Systemd is flaky and bloated. I guess for certain enterprise applications people unfamiliar with Unix might see the utility in it but there are many init replacements which are much better. Heck daemontools still competes favorably with systemd in terms of functionality.
Talking about "hardcore opposition" is a bit of a straw man. Put me in the continual "softcore opposition" camp. I don't care about it enough to move away from Debian or figure out how to switch to another init, and I was never in love with SysV init, but every time I have to debug systemd it's a pain in my ass.

Systemd suffers from being an underspecified declarative system. They look great when things work, but when they go wrong you're left with an opaque mess. For example, creating a dependency loop results in arbitrary units simply being dropped at boot time. On a desktop machine, you might only realize this when trying to figure out why some service didn't start and digging through the logs!

Of course there is nothing else systemd could possibly do instead, given a loop in a dependency DAG (besides refuse to boot completely). The problem is the design decision of using a simplistic data model that fails in that spectacular and unintuitive way.

One thing I've found helpful when Debian systems are causing problems is (1) ignore the config churn and (2) just attach GDB to edit raw memory, to make a process stop doing whatever it is that it's doing. It shouldn't be necessary but sadly in a world where engineering practices "evolve" this rapidly that's usually easier.
> The problem is the design decision of using a simplistic data model that fails in that spectacular and unintuitive way.

I don't see how it could be made intuitive. How would you design it?

Ideally ordering would be assured by construction, as if units were listed out in one file. But that would not compose easily.

I'd start by adding an optional priority number to each unit, which if supplied would form an ordering that units were always executed in. A unit having the priority number should also be less likely to be chosen for dropping, as they'd likely to be distribution-supplied units that were better debugged. This would make it much easier to narrow down the source of a logical conflict, and drop sensible units.

That only addresses the one gripe I brought up as an example though, and not the general pattern. For instance another issue I've run into is this automagical hacks that parse fstab crypttab etc and make units at boot time, while not actually supporting all the customary options of those files.

In general it feels like if systemd were written in a modern language, traditional distribution responsibilities (eg initrd/cryptoroot) could have been comprehensively replaced. But instead they bit off more than they could chew in C, so completeness and elegance were cast aside, and we're left with a hodgepodge of the old and new systems.

> That only addresses the one gripe I brought up as an example though, and not the general pattern. For instance another issue I've run into is this automagical hacks that parse fstab crypttab etc and make units at boot time, while not actually supporting all the customary options of those files.

Maybe the long term plan is to have these files dropped and replaced with something more systemd like?

> we're left with a hodgepodge of the old and new systems.

Same argument: if the long term goal is to completely overhawl the system, then at any point before that goal is reached there has to be old devices still in place.

That being said, I don't know much about systemd, not about the long term goals of systemd authors. I think that Poettering language of choice is C, so this explains that, but there's always room for other solutions in the FOSS world.

If anyone else finds the Linux userspace boot debate confusing, try running:

    strace -ff dig icann.org 2>&1 | tee ~/dns.log
I normally don't care that much about DNS. At least not until I notice things like a fresh Linux install having a 1000+ millisecond lag to curl a file. Then maybe try to fix it using the standard textbook technique of editing /etc/resolve.conf and then noticing the system somehow reverts my edit within microseconds.

Those are the sorts of engineering practices that help me learn about all the interesting things our Linux community friends like Systemd are doing to... enrich the domain resolution process.

Take a look. What you find may surprise you.

I'll stick my head out and say thanks, but no thanks systemd, I'm quite happy with OpenRC until something better comes along that doesn't attempt to assimilate everything under the sun and and includes the kitchen sjnk.
Disclaimer: I word for Red Hat, but I'm here as a guy not as a RH employee

I was anti-systemd until I read the "Rethinking PID 1" blog post by Lennart Poettering[1]. I also became a huge advocate of "documenting decisions and history" because as a reader getting to see the thought process softened me up. It also reminded me that real life is sometimes a messy tradeoff of decisions.

That said I don't like the ever-growing scope creep either. Systemd is great to work with (not perfect, but nothing is) but I do worry about systemd encroaching on everything.

I would love to see Lennart or somebody else driving things write a new "Rethinking PID 1" that explains the thought process behind the different scope creeps. That would really help people like me make an honest judgment.

[1] http://0pointer.de/blog/projects/systemd.html