WSL(Windows Subsystem for Linux)早期是不支持systemd的。后来WSL增加了systemd支持之后,之前安装过的发行版需要在发行版内/etc/wsl.conf
文件中增加systemd=true
设置才能启用systemd。我使用了很久的Ubuntu发行版启用systemd之后却遇到了一个问题:缺少/run/user/<uid>
目录,导致部分软件运行失败。如果手动创建这个文件夹,在WSL重启之后这个文件夹就会自动消失,令人十分烦恼。而此时全新安装的Ubuntu 24.04 LTS、Ubuntu 22.04 LTS、Ubuntu 20.04 LTS这些WSL发行版,虽然默认启用了systemd,但也能正确创建/run/user/<uid>
目录。说明这不是WSL本身的问题,而是发行版自身状态有问题。
查阅手册(man user@.service
)发现,/run/user/<uid>
目录是由user-runtime-dir@<uid>.service
这个systemd服务创建的。使用systemctl
命令查询发现,该服务在故障的发行版中处于不活动(inactive)状态,而在正常发行版中处于活动(active)状态:
# 故障的发行版
$ systemctl status user-runtime-dir@1000.service
○ user-runtime-dir@1000.service - User Runtime Directory /run/user/1000
Loaded: loaded (/usr/lib/systemd/system/user-runtime-dir@.service; static)
Active: inactive (dead) since Tue 2025-04-08 18:15:40 CST; 15min ago
Duration: 1min 57.566s
Docs: man:user@.service(5)
Process: 767 ExecStart=/usr/lib/systemd/systemd-user-runtime-dir start 1000 (code=exited, status=0/SUCCESS)
Process: 972 ExecStop=/usr/lib/systemd/systemd-user-runtime-dir stop 1000 (code=exited, status=0/SUCCESS)
Main PID: 767 (code=exited, status=0/SUCCESS)
...
# 正常的发行版
$ systemctl status user-runtime-dir@1002.service
● user-runtime-dir@1002.service - User Runtime Directory /run/user/1002
Loaded: loaded (/usr/lib/systemd/system/user-runtime-dir@.service; static)
Active: active (exited) since Tue 2025-04-08 18:31:45 CST; 6s ago
Docs: man:user@.service(5)
Process: 376 ExecStart=/usr/lib/systemd/systemd-user-runtime-dir start 1002 (code=exited, status=0/SUCCESS)
Main PID: 376 (code=exited, status=0/SUCCESS)
...
通过systemctl list-dependencies
命令可以了解到,该服务被session-1.scope
依赖,而这个依赖它的scope自身却处于失败(failed)状态,导致这个user-runtime-dir
服务由于不被任何单元依赖而自动停止,从而删除了我们的/run/user/<uid>
文件夹:
$ systemctl list-dependencies --reverse --all user-runtime-dir@1000.service
× ├─session-1.scope
○ └─user@1000.service
× └─session-1.scope
通过journalctl
查询日志,发现了这些异常日志:
systemd-networkd-wait-online[322]: Timeout occurred while waiting for network connectivity.
systemd[1]: systemd-networkd-wait-online.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: systemd-networkd-wait-online.service: Failed with result ’exit-code'.
systemd[1]: Failed to start systemd-networkd-wait-online.service - Wait for Network to be Configured.
这一段是说systemd-networkd-wait-online.service
服务启动失败。这是systemd-networkd中用于等待网络连接的服务。理论上WSL不需要发行版内的systemd-networkd来管理网络状态,而是由Windows来管理。在正常的发行版中检查发现,这个服务是处于禁用状态的。
systemd[1]: session-1.scope: PID 638 vanished before we could move it to target cgroup ‘/user.slice/user-1000.slice/session before we could move it to target cgroup ‘/user.slice/user-1000.slice/session-1.scope’, skipping: No such process
systemd[1]: session-1.scope: No PIDs left to attach to the scope’s control group, refusing.
systemd[1]: session-1.scope: Failed with result ‘resources’.
这一段大概意思是,由于进程638已经退出,session-1.scope
启动失败。638是login进程,此处并不明确login进程退出的原因。
GitHub和LaunchPad上的网友提示,直接禁用systemd-networkd
服务可解决systemd-networkd-wait-online.service
超时的问题。尝试使用systemctl
命令禁用该服务:
sudo systemctl disable systemd-networkd
之后在Windows命令行中退出WSL:
wsl --shutdown
再次启动原本有问题的发行版,发现/run/user/<uid>
目录已经自动创建,且user-runtime-dir@<uid>.service
也已经处于活动状态。而这时session-1.scope
失败的问题也自动解决了。