jjx*_*tra 16 c# windows-subsystem-for-linux .net-5
我正在尝试在 Windows 上使用 Ubuntu 调试 WSL 2 中的一些 C# / .NET 5 代码。我在 Windows 10 上安装了 WSL 2,并且想要测试创建 Systemd 服务。不幸的是,默认情况下 Systemd 似乎并未随 WSL 2 一起启用,尽管标准 Ubuntu 安装默认情况下已启用它。有什么方法可以在 WSL 2 中启用 Systemd 吗?
Not*_*1ds 18
注意:有关此社区 Wiki 的背景信息,请参阅此答案底部的脚注。
在 WSL2(但不是 WSL1)上启用 Systemd 有多种可能的途径。这里总结了这些内容,下面提供了更多详细信息。
虽然不是这个问题的一部分,但对于那些只想运行某些需要 Systemd 的应用程序的人来说,还有其他选择:
在 WSL1 和 WSL2 上:
sudo service <service_name> start
)(如果可用)仅在 WSL2 上:
首先,考虑是否应该或需要在WSL 中启用 Systemd。启用 Systemd 将自动启动许多在 WSL 下可能不需要的后台服务和任务。因此,它还会增加 WSL 启动时间,尽管影响取决于您的系统。检查下面的“替代方案”部分,看看是否有更好的选择可以满足您的需求。例如,该service
命令可以执行您需要的操作,而无需任何额外的工作。
Microsoft 现在已在 WSL2应用程序版本中集成了 Systemd 支持(而不是较旧的“Windows 功能”实现)。
从 WSL 应用程序版本 1.0.0 开始,此功能在 Windows 10 和 Windows 11 上均可用。Windows 10 用户确实需要使用 UBR(更新版本)2311 或更高版本。UBR 是完整 Windows 内部版本号的最后 4 位数字(例如,Windows 10 22H2 为 10.0.19045.2311)。2311 与KB5020030一起安装,这是一个可选的预览更新,但如果您稍后阅读本文,它可能是稍后的(非预览)每月服务更新。
如果您使用的是受支持的 Windows 版本,则可以安装支持 Systemd 的 WSL 应用程序:
通过 Microsoft Store(作为“Linux 的 Windows 子系统”)。
或者从Github 存储库中的发布页面。要手动安装版本:
重新启动(以确保 WSL 根本未在使用)。简单的wsl --shutdown
可能会起作用,但通常不会。
从上面的链接下载 1.0.0(或更高版本)版本。
启动管理员 PowerShell 并:
Add-AppxPackage <path.to>/Microsoft.WSL_1.0.0.0_x64_ARM64.msixbundle
wsl --version # to confirm
Run Code Online (Sandbox Code Playgroud)
要启用此功能,请在 WSL 下启动 Ubuntu(或其他 Systemd)发行版(通常就wsl ~
可以工作)。
sudo -e /etc/wsl.conf
Run Code Online (Sandbox Code Playgroud)
添加以下内容:
[boot]
systemd=true
Run Code Online (Sandbox Code Playgroud)
退出 Ubuntu 并再次:
wsl --shutdown
Run Code Online (Sandbox Code Playgroud)
然后重新启动Ubuntu。
sudo systemctl status
Run Code Online (Sandbox Code Playgroud)
...应该显示您的 Systemd 服务。
有许多可从各种来源获得的 Systemd 启用脚本。鉴于在 WSL 下运行 Systemd 所涉及的复杂性,建议您:
使用一个积极维护的
尝试尽可能多地了解它们的运作方式,以及它们如何影响您的 WSL 发行版中的其他功能和应用程序
在此或任何其他网站上提问时,请在问题中披露您正在使用的脚本,以便其他人可以尝试在适当的上下文中理解和/或重现您的问题
在 WSL2 下启用 Systemd 的几个比较流行的项目是:
Genie:1.8k 星,最后一次提交 2022 年 9 月
Distrod:1.4k 颗星,最后一次提交于 2022 年 7 月
WSL2-Hacks:1.1k 星,大部分是指导性的,带有支持脚本示例。最后一次提交 2022 年 1 月
从本质上讲,它们都遵循下一个选项中涵盖的相同原则......
在早期版本的 WSL 中运行 Systemd 的主要问题之一是两个 init 都需要是 PID 1。为了解决这个问题,可以创建一个新的命名空间或容器,其中 Systemd 可以作为 PID 1 运行。
要了解这是如何完成的(在非常基础的层面上):
跑步:
sudo -b unshare --pid --fork --mount-proc /lib/systemd/systemd --system-unit=basic.target
Run Code Online (Sandbox Code Playgroud)
这将在一个具有自己的 PID 映射的新命名空间中启动 Systemd。在该命名空间内,Systemd 将是 PID1(因为它必须运行)并拥有所有其他进程。然而,“真正的”PID 映射仍然存在于该命名空间之外。
请注意,这是启动 Systemd 的“最低限度”命令行。它至少不会支持:
.exe
)上面列出的脚本和项目需要做额外的工作才能让这些东西正常工作。
等待几秒钟 Systemd 启动,然后:
sudo -E nsenter --all -t $(pgrep -xo systemd) runuser -P -l $USER -c "exec $SHELL"
Run Code Online (Sandbox Code Playgroud)
这将进入命名空间,您现在可以使用ps -efH
它来查看它systemd
在该命名空间中作为 PID 1 运行。
此时,您应该可以运行了systemctl
。
并且在向自己证明这是可能的之后,建议您完全退出所有 WSL 实例,然后执行wsl --shutdown
. 否则,有些东西会被“破坏”直到你这样做为止。它们可能会被“修复”,但这超出了这个答案的范围。如果您有兴趣,请参考上面列出的项目,看看他们是如何处理这些情况的。
sudo service <service_name> start
)(如果可用)在 Ubuntu、Debian 和 WSL 上的其他一些发行版中,许多常见的系统服务仍然具有init.d
可用于代替systemctl
Systemd 单元的“旧”脚本。您可以使用 来查看这些 ls /etc/init.d/
。
因此,例如,您可以以 开头ssh
,sudo service ssh start
它将/etc/init.d/ssh
使用start
参数运行脚本。
即使某些非默认软件包(例如 MySql/MariaDB)也会安装 Systemd 单元文件和旧init.d
脚本,因此您仍然可以对service
它们使用该命令。
另一方面,某些软件包(例如 Elasticsearch)仅安装 Systemd 单元。某些发行版仅为其存储库中的大多数(如果不是全部)包提供 Systemd 单元。
对于那些没有等效初始化脚本的服务,可以“手动”运行它们。
为简单起见,我们假设该ssh
init.d
脚本不可用。
在这种情况下,“答案”是找出 Systemd 单元文件正在做什么,并尝试手动复制它。这在复杂性上可能有很大差异。但我首先查看您尝试运行的 Systemd 单元文件:
less /lib/systemd/system/ssh.service
Run Code Online (Sandbox Code Playgroud)
# Trimmed
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
Run Code Online (Sandbox Code Playgroud)
一些不太相关的行已被修剪,以使其更易于解析,但您可以man systemd.exec
、man systemd.service
和其他选项来查看大多数选项的作用。
在这种情况下,当您 时sudo systemctl start ssh
,它:
$SSHD_OPTS
)/etc/default/ssh
/run/sshd
(来自man systemd.exec
)。当您停止服务时,这也会删除运行时目录。/usr/sbin/sshd
使用选项运行因此,如果您没有任何基于环境的配置,您可以设置一个脚本来:
/run
,这是一个tmpfs
挂载,因此每次 WSL 实例重新启动后都会将其删除。0755
/usr/sbin/sshd
以 root 身份启动...如果没有 Systemd,您也可以手动完成同样的事情。
同样,这可能是最简单的例子。您可能需要完成更多更复杂的任务。
许多包/服务都可以作为 Docker 镜像提供。Docker 通常在 WSL2 上的 Ubuntu 下运行得很好(特别是 WSL2;它不能在 WSL1 上运行)。如果您尝试启动的服务没有 SysVinit“服务”脚本,则很可能有一个在容器化环境中运行的可用 Docker 映像。
示例:Elasticsearch,如本问题所示。
Dockerfile
以了解服务是如何在没有 Systemd 的情况下启动的。有关详细信息,请参阅下一个选项 - “手动方式”。Microsoft 建议使用 Docker Desktop for Windows 在 WSL2 下运行 Docker 容器。
脚注该答案作为社区 Wiki 发布,因为它可以适用于多个 Stack Overflow 问题。它最初是基于询问 Ubuntu 问题的答案。然而,随着 Systemd 在 WSL 上的发展,社区希望这个 wiki 答案能够不断更新。
选择这个问题的原因是:
这似乎是最规范、最直接的“如何在 WSL 上启用 Systemd?” 问题。
这是切题的,因为*创建 Systemd 服务对于编程来说是(或者至少可以是)独特的。
归档时间: |
|
查看次数: |
13055 次 |
最近记录: |