WSL2 现已官方支持 Systemd,可实际上手体验后发现 WSL2 中 Systemd 处于降级状态。本文将分析 WSL2 中 Systemd 处于降级状态的原因并附上解决方案。

序言

2022年11月22日,Microsoft 终于宣布 WSL 脱离预览阶段并带来了人们翘首以盼的 Systemd 官方支持

然而实际上手体验后,我发现 WSL2 中 Systemd 处于降级状态,希望 Microsoft 尽快修复此 BUG。

> systemctl status
● Anonimowy
    State: degraded
     Jobs: 0 queued
   Failed: 1 units

接下来,本文将分析问题原因并附上解决方案。

问题何在?

首先,我们找出导致 Systemd 进入降级状态的罪魁祸首:

> systemctl --failed
  UNIT                     LOAD   ACTIVE SUB    DESCRIPTION
● systemd-sysusers.service loaded failed failed Create System Users

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.
1 loaded units listed.

显而易见的,systemd-sysusers.service 启动失败导致了 Systemd 降级。

查看 systemd-sysusers.service 错误日志:

> journalctl --boot -u systemd-sysusers.service
Nov 30 00:00:00 Anonimowy systemd[58]: systemd-sysusers.service: Failed at step CREDENTIALS spawning systemd-sysusers: Protocol error
Nov 30 00:00:00 Anonimowy systemd[1]: systemd-sysusers.service: Main process exited, code=exited, status=243/CREDENTIALS
Nov 30 00:00:00 Anonimowy systemd[1]: systemd-sysusers.service: Failed with result 'exit-code'.
Nov 30 00:00:00 Anonimowy systemd[1]: Failed to start Create System Users.

查看 systemd-sysusers.service 单元文件:

> systemctl cat systemd-sysusers.service
# /lib/systemd/system/systemd-sysusers.service
#  SPDX-License-Identifier: LGPL-2.1-or-later
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Create System Users
Documentation=man:sysusers.d(5) man:systemd-sysusers.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-remount-fs.service
Before=sysinit.target shutdown.target systemd-update-done.service
ConditionNeedsUpdate=/etc

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=systemd-sysusers
TimeoutSec=90s

# Optionally, pick up a root password and shell for the root user from a
# credential passed to the service manager. This is useful for importing this
# data from nspawn's --set-credential= switch.
LoadCredential=passwd.hashed-password.root
LoadCredential=passwd.plaintext-password.root
LoadCredential=passwd.shell.root

systemd-sysusers.service 的作用是创建系统用户和系统组,而导致该系统服务单元失败的原因是以下几行配置:

LoadCredential=passwd.hashed-password.root
LoadCredential=passwd.plaintext-password.root
LoadCredential=passwd.shell.root

LoadCredential 和其他凭证选项若想要正常工作,Shared Memory Virtual Filesystem 必须挂载在 Systemd 期望的位置,也就是 /dev/shm。然而目前,WSL2 却将其挂载在 /run/shm 并将 /dev/shm 链接到 /run/shm

> l /dev/shm
lrwxrwxrwx 1 root root 8 Nov 30 00:00 /dev/shm -> /run/shm

这意味着任意使用这些选项的单元都将无法正常运作。

例如,Snap 就将受 shm 位置影响

解决方案

创建 /etc/systemd/system/fix-shm.service

> sudo systemctl edit --force --full fix-shm.service
> systemctl cat fix-shm.service
# /etc/systemd/system/fix-shm.service
[Unit]
Description=Fix /dev/shm Issue
Before=sysinit.target
DefaultDependencies=no
ConditionPathExists=/dev/shm
ConditionPathIsSymbolicLink=/dev/shm
ConditionPathIsMountPoint=/run/shm

[Service]
Type=oneshot
ExecStart=/usr/bin/rm /dev/shm
ExecStart=/bin/mount --bind -o X-mount.mkdir /run/shm /dev/shm

[Install]
WantedBy=sysinit.target

开机自动启用单元

> sudo systemctl enable fix-shm.service

立即终止所有正在运行的发行版和 WSL2 轻型实用程序虚拟机

> wsl --shutdown

重新启动 WSL2 并查看 Systemd 状态

> systemctl status
● Anonimowy
    State: running
     Jobs: 0 queued
   Failed: 0 units

现在 Systemd 正常运作,问题完美解决,希望 Microsoft 尽快修复此 BUG。