Update (2020/08/07): Since publishing this post I’ve added a bit more to the script used to enter the Systemd namespace. The latest version supports VSCode properly, with the bonus that the VSCode inbuilt shell is now correctly within the Systemd namespace.
Update (2020/08/20): Add fallback Systemd startup script for when you have run either wsl.exe --terminate $DISTRONAME
or wsl.exe --shutdown
, causing Systemd to be not running when starting the shell.
So, I wrote about and made a video about my hack to get Systemd running in WSL2. Now, I’ve managed to improve the performance of this hack by reducing the amount of indirection and moving the start-up of Systemd to be handled by Windows’ Task Scheduler.
First, we need an Ubuntu or other distro with daemonize
installed. For the Ubuntu releases from the Windows Store you need to run the following:
sudo apt update
sudo apt install -yyq daemonize
Code language: Bash (bash)
Next, we need a small script in /etc/profile.d
to set up some variables when we login to WSL2:
export WSL_INTEROP="$(ls -t /run/WSL/*_interop | head -1)"
export DISPLAY="$(awk '/namespace/ { print $2":0" }' /etc/resolv.conf)"
if [ -f "$HOME/.wsl_env" ]; then
set -a; source "$HOME/.wsl_env"; set +a
fi
Code language: Bash (bash)
Moving on, we need a new file called /usr/bin/namespaced-shell-wrapper
, which we symlink to /bin/namespaced-bash
. This will then chain into /bin/bash
. If you want to use an alternative shell such as /usr/bin/zsh
you would symlink the wrapper to /usr/bin/namespaced-zsh
. In this way it is anticipated that we can use any shell we desire.
#!/bin/sh
ME="$0"
SHELL="$(echo "$0" | sed -e 's/namespaced-//')"
if [ "$1" = "-c" ]; then
# this is for VSCode support
shift
SAVE_CMD="$@"
if echo "$1" | grep -q '^sh -c'; then
SAVE_CMD_NOSH="$(echo "$1" | sed -e 's/^sh -c//')"
SAVE_CMD="$(eval echo "$SAVE_CMD_NOSH")"
shift
fi
eval echo "$SAVE_CMD" > "$HOME/.wsl_cmd"
fi
if [ "$USER" != "root" ]; then
export > "$HOME/.wsl_env"
exec sudo "$ME"
fi
SYSTEMD_PID="$(ps -eo pid=,args= | awk '$2" "$3=="systemd --unit=multi-user.target" { print $1 }')"
if [ -z "$SYSTEMD_PID" ]; then
/usr/bin/daemonize /usr/bin/unshare --fork --mount-proc --pid -- /bin/sh -c "mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc; exec systemd --unit=multi-user.target"
while [ -z "$SYSTEMD_PID" ]; do
sleep 1
SYSTEMD_PID="$(ps -eo pid=,args= | awk '$2" "$3=="systemd --unit=multi-user.target" { print $1 }')"
done
sleep 1
fi
CMD_FILE="$(eval echo "~$SUDO_USER/.wsl_cmd")"
if [ -f "$CMD_FILE" ]; then
trap "rm -f '$CMD_FILE'" EXIT
nsenter -a -t "$SYSTEMD_PID" sudo -u "$SUDO_USER" "$SHELL" -c "$CMD"
else
exec nsenter -a -t "$SYSTEMD_PID" su --pty --shell="$SHELL" --login "$SUDO_USER"
fi
Code language: Bash (bash)
We need another file at /etc/sudoers.d/namespaced-shells
to allow password-less sudo
for your chosen shells’ wrapper symlink to chain into itself as root. It should include something like below:
%sudo ALL=(ALL) NOPASSWD: /bin/namespaced-bash
Code language: plaintext (plaintext)
To set your shell you now need to execute the following:
sudo chsh -s /bin/namespaced-bash $USER
Code language: Bash (bash)
Finally, we need a Scheduled Task in Windows Task Scheduler to execute the following command on login to Windows. Make sure you remember to uncheck the “Start the task only if the computer is on AC power” option so that it starts Systemd if you’re on battery power when you login (this is in the “Conditions” tab of the task’s properties dialog):
wsl.exe -d Ubuntu -u root -e /bin/sh -c "/usr/bin/daemonize /usr/bin/unshare --fork --mount-proc --pid -- sh -c 'mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc; exec systemd --unit=multi-user.target'"
Code language: DOS .bat (dos)

If your chosen distribution is not Ubuntu, you might need to adjust the path to daemonize
, unshare
and/or systemd
as appropriate. If you adjust the path to systemd
then you also need to adjust it in the namespaced-shell-wrapper
script to match. You need to set -d Ubuntu
to your chosen WSL2 instance’s name for your system, e.g. -d openSUSE-Leap-15.2
.
Systemd started a login final thought
This method speeds up entering WSL2 because we don’t need to go through a long chain of exec
calls with various scripts and commands chaining into themselves to get Systemd running. Instead we start Systemd when we login to Windows so unless you terminate the distro or shutdown WSL2 it will always be ready.
Hat tip to Brian Ketelsen for their Tweet that got me thinking about this method.