I use WSL2 on Windows 11. I want to run the systemctl command in Ubuntu 20.04, but it gives me the following error:
System has not been booted with systemd as init system (PID 1).
Can't operate. Failed to connect to bus: Host is downHow can I fix it?
91 Answer
Surprisingly, after 5 years or so of WSL, there doesn't seem to be a good, general-purpose "Systemd" question here on Ask Ubuntu. So this looks like a good one to use for that purpose.
The problem
In general, when you see either of the following two messages:
System has not been booted with systemd as init system (PID 1). Can't operate.Failed to connect to bus: Host is down
Then it's typically the same root cause. In the case of systemctl and attempting to start ssh, you are seeing both.
The core problem, as mention in the comments, is that WSL doesn't use Systemd, even in distributions where it is the default. Instead, WSL currently uses its own /init process as PID 1, which performs a few WSL-specific tasks that I mention in this answer (so I won't repeat them here).
And while WSL is (IMHO) a great way to have a full-featured Linux CLI in Windows (and recently, even GUI), the lack of Systemd does tend to make things more difficult in distributions that expect it to be there. Fortunately, Ubuntu is pretty good overall about being able to cope without Systemd.
How to handle the lack of Systemd
And regardless, Systemd at its core is just a (probably gross-oversimplification) "way of accomplishing system tasks". There is usually (but not always, see footnote below) a way of doing the same task without Systemd, and often more than one way.
Option 1: "The old way"
In Ubuntu on WSL, many of the common system services still have the "old"
init.dscripts available to be used in place ofsystemctlwith Systemd units. You can see these by usingls /etc/init.d/.So, for example, you can start
sshwithsudo service ssh start, and it will run the/etc/init.d/sshscript with thestartargument.Even some non-default packages such as MySql/MariaDB will install both the Systemd unit files and the old
init.dscripts, so you can still use theservicecommand for them as well.Option 2: "The 'manual' way"
But some services don't have a init-script equivalent, especially on other distributions. For simplicity, let's assume that the
sshinit.dscript wasn't available.In this case, the "answer" is to figure out what the Systemd unit files are doing and attempt to replicate that manually. This can vary widely in complexity. But I'd start with looking at the Systemd unit file that you are trying to run:
less /lib/systemd/system/ssh.service# Trimmed [Service] EnvironmentFile=-/etc/default/ssh ExecStartPre=/usr/sbin/sshd -t ExecStart=/usr/sbin/sshd -D $SSHD_OPTS RuntimeDirectory=sshd RuntimeDirectoryMode=0755I've trimmed out some of the less relevant lines for understanding its behavior, but you can
man systemd.exec,man systemd.service, and others to see what most of the options do.In this case, when you
sudo systemctl start ssh, it:- Reads environment variables (the
$SSHD_OPTS) from/etc/default/ssh - Tests the config, exits if there is a failure
- Makes sure the RuntimeDirectory exists with the specified permissions. This translates to
/run/sshd(fromman systemd.exec). This also removes the runtime directory when you stop the service. - Runs
/usr/sbin/sshdwith options
So, if you don't have any environment-based config, you could just set up a script to:
- Make sure the runtime directory exists. Note that, since it is in
/run, which is atmpfsmount, it will be deleted after every restart of the WSL instance. - Set the permissions to
0755 - Start
/usr/sbin/sshdas root
... And you would have done the same thing manually without Systemd.
Again, this is probably the simplest example. You might have much more to work through for more complex tasks.
- Reads environment variables (the
Option 3: Run Systemd as PID 1 in a PID namespace/container
Finally, it's possible to get Systemd running under WSL2 (but not WSL1). This is a fairly advanced topic, although there are multiple scripts and projects that attempt to simplify it. Even so, my personal recommendation is to make sure that you understand what is going on behind the scenes should you use one of these techniques.
Let's start with some of the more popular projects to enable Systemd in WSL:
I haven't personally run any of them, but all are open-source, and I've scanned the source to compare the techniques. At the core, each creates a new namespace or container where Systemd can run as PID 1.
You can see this in action by following the steps:
Run:
sudo -b unshare --pid --fork --mount-proc /lib/systemd/systemd --system-unit=basic.targetThis starts Systemd in a new namespace with its own PID mapping. Inside that namespace, Systemd will be PID1 (as it must, to function) and own all other processes. However, the "real" PID mapping still exists outside that namespace.
Note that this is a "bare minimum" command-line for starting Systemd. It will not have support for, at least:
- Windows Interop (the ability to run Windows
.exe) - The Windows PATH (which isn't necessary without Windows Interop anyway)
The scripts and projects listed above do extra work to get these things working as well.
- Windows Interop (the ability to run Windows
Wait a few seconds for Systemd to start up, then:
sudo -E nsenter --all -t $(pgrep -xo systemd) runuser -P -l $USER -c "exec $SHELL"This enters the namespace, and you can now use
ps -efHto see thatsystemdis running as PID 1 in that namespace.At this point, you should be able to run
systemctl.And after proving to yourself that it's possible, I recommend exiting all WSL instances completely, then doing
wsl --shutdown. Otherwise, you will have some things be "broken" until you do. They can likely be "fixed", but that's beyond the scope of any one Ask Ubuntu question ;-). My recommendation is to refer to the projects above to see how they handle it.
Footnote
There are cases where certain software expects Systemd and just won't work (or at least not fully) if it isn't present. One that I came across recently is Cockpit.
While I was able to get it up and running without Systemd, it ultimately expects Systemd to be present in order to execute many, if not most, functions. In effect, parts of Cockpit are a front-end to Systemd.
This type of software, one that executes Systemd commands (such as systemctl), may be the exception to the "there's an alternative" rule.