Celeste aka. 73chn0 Asked: 2022-05-05 08:58:44 +0800 CST2022-05-05 08:58:44 +0800 CST 2022-05-05 08:58:44 +0800 CST WSL/WSL2/WSLg 在没有 systemd 的情况下如何工作? 772 据我了解,systemd 是 Linux 的“主”守护进程,在它启动并运行它的 init 函数后立即管理所有其他进程。由于我遇到了这个(现已解决)问题,即我意识到无法在 WSL 上使用任何 systemd 命令,因此它根本没有 systemd 进程。 现在,出于好奇,我想知道 WSL 依赖哪个进程管理而不是 systemd。由于我没有在“通用谷歌搜索”上找到令人满意的答案,我想,让我们在这里试试吧。 linux process 4 个回答 Voted Best Answer NotTheDr01ds 2022-05-05T12:38:37+08:002022-05-05T12:38:37+08:00 更新:截至今天,微软已从WSL 0.67.2(目前为预览版)开始在 WSL2 中集成 Systemd 支持。正如我的原始答案(如下)和此处的其他人所述,这不是必需的,并且是可选的。 0.67.2 预览版可用: 在 Microsoft Store 中的 Windows 11 Insider 构建(作为“Linux 预览版的 Windows 子系统”)) 或者从Github 存储库中的Releases页面。 请注意,它仅适用于 Windows 11。较新的 WSL 版本不适用于 Windows 10。 在这一点上,我自己还没有测试过这个功能,但我很快就会测试。 我最初的想法是,在当前设计中使用它时要非常小心。开发博客发表声明: systemd 服务不会使您的 WSL 实例保持活动状态。您的 WSL 实例将像以前一样保持活动状态 换句话说,如果(例如)您启用 MariaDb 以通过其 Systemd 单元运行,它将在您退出最后一个 shell 后不久终止,除非您正在运行其他一些后台服务。除非有所改变,否则这不是“安全”的终止。 当我知道更多时,我会用更多信息更新这个答案。 原始答案,这仍然适用于 WSL 的现有发布版本,尤其是在无法更新以使用上述新版本的 Windows 10 系统上。 好问题——这里有很多有趣的东西要讲! 首先,让我们建立一些术语: systemd 是 Linux 的“主”守护进程,在它启动并运行它的 init 函数后立即管理所有其他进程。 首先,@mascoj 在评论中的一个要点是Linux根本不需要Systemd。它肯定在绝大多数 Linux 发行版中使用,但还有其他替代品(正如@user1686 的回答提到的那样),它们都早于 Systemd 并且自 Systemd 以来就已经出现。一些发行版默认使用这些替代方案,因此(个人意见)其中一些发行版在 WSL 下可能会更好地工作。 在高层次上,Systemd 通常提供以下几个功能: 初始化系统:执行启动时系统初始化(例如创建或清理临时文件等) 在启动时运行服务(例如cron、sshd、mariadb等) PID 1 进程:所有其他进程所在的主进程 流程主管(又名流程管理器):启动、监控、重新启动附加服务 附加服务(Systemd 做了很多工作,例如日志记录、挂载等等) 这些功能中的大多数都可以单独处理,但 Systemd 可以“全部完成”。 一些发行版和系统不依赖于 Systemd 并且不那么单一地做事情。例如,某些系统在启动期间的某个时间点将 init 系统的控制权移交给单独的进程管理器。进程主管可能也可能不是 PID1。如果不是,则通常 Init 进程保持为 PID1 并且进程主管在其下运行。进程管理器通常有一个启动时需要的服务列表,它会执行和监控这些服务。 一些发行版(我想到了 Artix,我也相当肯定 Gentoo)允许您混合和匹配来自几个不同的初始化系统和进程管理器。 现在让我们从高层次上讨论标题中的问题: 没有 Systemd,WSL/WSL2/WSLg 如何工作? WSL2: 重要的是要了解,当您运行 WSL2 发行版时,该发行版并未在虚拟机中运行。WSL2本身正在运行一个具有自己发行版的虚拟机(如果我不得不猜测的话,可能是基于Mariner的)。 在隐藏的虚拟机内部是您的发行版在其自己的一组命名空间中运行的地方。如果你在 WSL2 中同时运行多个发行版,它们都在同一个 VM 中运行,每个都有自己的: PID 命名空间 挂载命名空间 IPC 命名空间 UTS 命名空间 WSLg 系统分发(仅限 Windows 11) 但是,它们都与父 WSL2 VM 共享以下内容(因此彼此共享): 用户命名空间 网络命名空间 Cgroup 命名空间 设备树(除/dev/pts) CPU/内核/内存/交换(显然) /init二进制(但不是进程) 这与容器系统(例如 Docker 或 Podman(以及其他))的工作方式非常非常相似。 在大多数(但肯定不是全部)容器中,您会发现很少有进程主管正在运行。 大多数容器都被启动它们的“外部”进程(例如 Docker)告知要启动哪些服务。在 WSL 的情况下,通常有一个wsl命令告诉 WSL 启动哪些服务。例如(一个过于简单的例子,不一定是一个很好的例子): wsl -e crond 但是,一个重要的区别是,与传统容器不同,WSL 始终拥有自己的以 PID1 运行的 Init 进程(原因见下文)。对于大多数其他容器类型,PID1 是您告诉它首先启动的进程。 WSL1 虽然 WSL1 在技术上不像 WSL2 那样“在容器/命名空间中运行”,但它确实共享相同的 Init 概念以实现互操作性。 记住 WSL1 并不支持所有 Linux 系统调用也很重要。WSL1 首次发布时,其覆盖率约为 70%。它在运行大量工具方面做得相当出色,但我感觉 Systemd 通常尝试启动的单元数量可能会暴露一些差距。 WSLg WSLg 在所谓的“系统发行版”中运行,该发行版绝对基于 Mariner 发行版。为每个尝试运行 GUI 应用程序的 WSL2 分发创建一个 WSLg 系统分发。 在这种情况下,如何启动必要的服务真的要由微软来决定。如果您愿意,您可以创建自己的系统发行版,Microsoft 提供了一个参考实现作为开始,但那里可能很少需要 Systemd 的功能。 这并不是说在 WSL(1 或 2)中运行进程管理器没有用 - 在某些情况下会。但就我个人而言,我很高兴 WSL 将其留给用户。这允许它在默认情况下像容器一样运行(快速启动,高效的资源使用),但在其他情况下更像(但不完全是)成熟的“虚拟操作系统”。 主要问题: 现在,出于好奇,我想知道 WSL 依赖哪个进程管理而不是 Systemd。 让我们把它分解成我们上面所说的 Systemd 处理的函数: PID1/Init 系统:如上所述,WSL 的专有/init系统用于这两个功能。之所以需要这个特殊/init功能,是因为它处理 Linux 和 Windows 之间的深度互操作集成。传统的 Linux 初始化系统(如 Systemd)不知道如何处理这个问题。 理论上,WSL2 可以使用 Systemd 启动并设置一些特殊服务来处理集成,但是: 这会增加非常精简的启动的开销 一些发行版不使用 Systemd,因此他们必须以不同的方式配置每个发行版(如果需要,最好将其留给用户)。 无论如何,它可能/init仍然需要 PID1,以便在启动后继续处理某些互操作功能。 由于 Systemd要求它是 PID1,这会产生一些冲突。我确实认为微软团队正在努力解决这个问题,但这显然还没有解决。 流程主管/经理:默认情况下,WSL2 确实没有。但是,正如@user1686 在另一个答案中指出的那样,直到最近这还不是问题。 为每个服务创建脚本service,命令(或类似命令)的入口点为启动/停止/重新启动/状态。 至少,Ubuntu 仍然为服务提供了许多这样的脚本。sshd因此,例如,当您想要 start 时,您可以只运行 run sudo service ssh start,然后调用它的脚本。如果您安装 Maridb ( sudo service mysql start),则相同。 但是,某些服务不提供 SysVInit 样式的脚本。他们可能只提供 Systemd 单元,至少在基于 Systemd 的发行版上。这些只是在 WSL 发行版上不起作用(很容易)。当发生这种情况时,请参阅这个答案,我会在其中介绍替代方案。 在启动时运行服务 在 Windows 10 下,仍然没有很好的方法来处理这个问题。当然,WSL 发行版并不真正“启动”,但它确实有一个定义的“第一次启动”,您可能希望在其中运行某些东西。 在 Windows 10 下,最好的办法是手动启动服务或通过用户启动文件(例如~/.bashrc)运行它们。有关这方面的一些想法,请参阅此答案。 但听起来你在 Windows 11 上(因为你提到了 WSLg),在这种情况下,有一个功能允许你指定一个命令(或一系列命令)在分发启动时运行一次。同样,请参阅此答案以获取有关如何配置的信息。 在启动时运行进程管理器 使用这些技术,完全可以运行您想要的任何进程管理器,只要它不需要它是 PID1。 到目前为止我在 WSL 上尝试过的一些方法: Supervisord专为在容器中运行服务而设计。 dinit -- 适用于Artix,这是一个基于 Arch 的发行版,它有 5 个不同的 init/process manager 选项可供您使用。 s6,也可用于 Artix。这个在 WSL2 下有一些问题,我认为他们在 WSL2 方面,但我不能确定。 s6 和 dinit 都倾向于认为它们(自然而然地)在物理/虚拟机上运行,因此它们尝试进行一些在 WSL 下不必要的启动。我已经能够删除不必要的项目,然后 dinit 至少运行得很好。不过,我还没有将这些内容整合到可供其他人使用的可重复说明中。 运行系统 甚至可以通过伪装来运行 Systemd,使其在 WSL2(但不是 WSL1)发行版内的新命名空间中作为 PID1 运行(正如我们所讨论的,它已经在其自己的命名空间中运行)。我个人不一定推荐它,但很多人都这样做。我在这个 AU 答案的结尾处介绍了其中的一些内容,所以我不会在这里重复。 user1686 2022-05-05T10:11:08+08:002022-05-05T10:11:08+08:00 Systemd 实际上是一个相当新的项目,于 2010 年左右开始。在它之前使用过很多其他的:sysvinit、upstart、init-ng、s6、launchd(我认为它曾经有过 Linux 版本)。由于各种原因,一些 Linux 发行版仍然不使用 systemd。 在所有这些中,systemd 是最接近您甚至可以称为“进程管理器”的系统。Linux 实际上根本不依赖进程管理器。任何进程都可以在决定不受控制的情况下直接创建(分叉)一个新的子进程。(确实如此不受控制,以至于当 systemd 开始编写诸如“注销应该杀死你的剩余进程”之类的东西时,战争就发生了。) systemd 和其他此类程序的真正主要工作只是成为一个服务管理器:自动启动某些特定进程,例如负责显示登录屏幕的守护进程(GDM,agetty),并且有时会在它们崩溃时重新启动它们. 但是一旦你进入登录屏幕,其他一切都可以在没有 systemd/init 参与的情况下发生。 事实上,对于 sysvinit,实际的 init 进程几乎没有做任何事情:它监督的唯一服务是 agetty。从字面上看,其他所有事情都是通过普通的 shell 脚本完成的,这些脚本从未正确地接触过 init。启动服务的命令?外壳脚本。整个初始启动过程?运行更多 shell 脚本的 shell 脚本。 因此,对于 WSL 之类的东西,它不想表现得像一个完整的系统(它不应该像一个在使用前必须启动的完整 VM;启动 WSL 意味着即时,就好像你真的在运行 Linux 应用程序一样在 Windows 上),初始化过程可以相当少。我真的不知道 WSL2 使用什么,但它可以是完全自定义的。 (对于 WSL1,甚至可能没有init进程,因为 WSL1 甚至不是 VM,而只是仍然直接在 Windows 上运行的特殊进程的集合。) Daniel B 2022-05-05T09:51:35+08:002022-05-05T09:51:35+08:00 WSL 2 有一个自定义的初始化系统,它不是开源的(至少我还没有找到源代码)。ps您可以使用或之类的工具查看其流程htop。 它是一个多调用二进制文件,至少执行以下操作: 运行 9p 服务器进行文件访问 在 WSL 2 分发容器内启动 shell 管理 WSL 2 分发容器 运行其他互操作的东西 您看不到所有这些进程/守护进程,因为有些进程/守护进程在所有 WSL 2 容器之外运行(在根命名空间中)。 不使用分发中可能存在或不存在的任何 init 系统。相反,shell 是使用配置的用户 ID 直接生成的。 kreemoweet 2022-05-05T09:25:04+08:002022-05-05T09:25:04+08:00 Systemd 不是 Linux 的固有部分;许多 Linux 发行版不使用它。WSL 将运行您安装的 Linux 发行版使用的任何内容。
更新:截至今天,微软已从WSL 0.67.2(目前为预览版)开始在 WSL2 中集成 Systemd 支持。正如我的原始答案(如下)和此处的其他人所述,这不是必需的,并且是可选的。
0.67.2 预览版可用:
请注意,它仅适用于 Windows 11。较新的 WSL 版本不适用于 Windows 10。
在这一点上,我自己还没有测试过这个功能,但我很快就会测试。
我最初的想法是,在当前设计中使用它时要非常小心。开发博客发表声明:
换句话说,如果(例如)您启用 MariaDb 以通过其 Systemd 单元运行,它将在您退出最后一个 shell 后不久终止,除非您正在运行其他一些后台服务。除非有所改变,否则这不是“安全”的终止。
当我知道更多时,我会用更多信息更新这个答案。
原始答案,这仍然适用于 WSL 的现有发布版本,尤其是在无法更新以使用上述新版本的 Windows 10 系统上。
好问题——这里有很多有趣的东西要讲!
首先,让我们建立一些术语:
首先,@mascoj 在评论中的一个要点是Linux根本不需要Systemd。它肯定在绝大多数 Linux 发行版中使用,但还有其他替代品(正如@user1686 的回答提到的那样),它们都早于 Systemd 并且自 Systemd 以来就已经出现。一些发行版默认使用这些替代方案,因此(个人意见)其中一些发行版在 WSL 下可能会更好地工作。
在高层次上,Systemd 通常提供以下几个功能:
cron
、sshd
、mariadb
等)这些功能中的大多数都可以单独处理,但 Systemd 可以“全部完成”。
一些发行版和系统不依赖于 Systemd 并且不那么单一地做事情。例如,某些系统在启动期间的某个时间点将 init 系统的控制权移交给单独的进程管理器。进程主管可能也可能不是 PID1。如果不是,则通常 Init 进程保持为 PID1 并且进程主管在其下运行。进程管理器通常有一个启动时需要的服务列表,它会执行和监控这些服务。
一些发行版(我想到了 Artix,我也相当肯定 Gentoo)允许您混合和匹配来自几个不同的初始化系统和进程管理器。
现在让我们从高层次上讨论标题中的问题:
WSL2:
重要的是要了解,当您运行 WSL2 发行版时,该发行版并未在虚拟机中运行。WSL2本身正在运行一个具有自己发行版的虚拟机(如果我不得不猜测的话,可能是基于Mariner的)。
在隐藏的虚拟机内部是您的发行版在其自己的一组命名空间中运行的地方。如果你在 WSL2 中同时运行多个发行版,它们都在同一个 VM 中运行,每个都有自己的:
但是,它们都与父 WSL2 VM 共享以下内容(因此彼此共享):
/dev/pts
)/init
二进制(但不是进程)这与容器系统(例如 Docker 或 Podman(以及其他))的工作方式非常非常相似。
在大多数(但肯定不是全部)容器中,您会发现很少有进程主管正在运行。
大多数容器都被启动它们的“外部”进程(例如 Docker)告知要启动哪些服务。在 WSL 的情况下,通常有一个
wsl
命令告诉 WSL 启动哪些服务。例如(一个过于简单的例子,不一定是一个很好的例子):但是,一个重要的区别是,与传统容器不同,WSL 始终拥有自己的以 PID1 运行的 Init 进程(原因见下文)。对于大多数其他容器类型,PID1 是您告诉它首先启动的进程。
WSL1
虽然 WSL1 在技术上不像 WSL2 那样“在容器/命名空间中运行”,但它确实共享相同的 Init 概念以实现互操作性。
记住 WSL1 并不支持所有 Linux 系统调用也很重要。WSL1 首次发布时,其覆盖率约为 70%。它在运行大量工具方面做得相当出色,但我感觉 Systemd 通常尝试启动的单元数量可能会暴露一些差距。
WSLg
WSLg 在所谓的“系统发行版”中运行,该发行版绝对基于 Mariner 发行版。为每个尝试运行 GUI 应用程序的 WSL2 分发创建一个 WSLg 系统分发。
在这种情况下,如何启动必要的服务真的要由微软来决定。如果您愿意,您可以创建自己的系统发行版,Microsoft 提供了一个参考实现作为开始,但那里可能很少需要 Systemd 的功能。
这并不是说在 WSL(1 或 2)中运行进程管理器没有用 - 在某些情况下会。但就我个人而言,我很高兴 WSL 将其留给用户。这允许它在默认情况下像容器一样运行(快速启动,高效的资源使用),但在其他情况下更像(但不完全是)成熟的“虚拟操作系统”。
主要问题:
让我们把它分解成我们上面所说的 Systemd 处理的函数:
PID1/Init 系统:如上所述,WSL 的专有
/init
系统用于这两个功能。之所以需要这个特殊/init
功能,是因为它处理 Linux 和 Windows 之间的深度互操作集成。传统的 Linux 初始化系统(如 Systemd)不知道如何处理这个问题。理论上,WSL2 可以使用 Systemd 启动并设置一些特殊服务来处理集成,但是:
这会增加非常精简的启动的开销
一些发行版不使用 Systemd,因此他们必须以不同的方式配置每个发行版(如果需要,最好将其留给用户)。
无论如何,它可能
/init
仍然需要 PID1,以便在启动后继续处理某些互操作功能。由于 Systemd要求它是 PID1,这会产生一些冲突。我确实认为微软团队正在努力解决这个问题,但这显然还没有解决。
流程主管/经理:默认情况下,WSL2 确实没有。但是,正如@user1686 在另一个答案中指出的那样,直到最近这还不是问题。 为每个服务创建脚本
service
,命令(或类似命令)的入口点为启动/停止/重新启动/状态。至少,Ubuntu 仍然为服务提供了许多这样的脚本。
sshd
因此,例如,当您想要 start 时,您可以只运行 runsudo service ssh start
,然后调用它的脚本。如果您安装 Maridb (sudo service mysql start
),则相同。但是,某些服务不提供 SysVInit 样式的脚本。他们可能只提供 Systemd 单元,至少在基于 Systemd 的发行版上。这些只是在 WSL 发行版上不起作用(很容易)。当发生这种情况时,请参阅这个答案,我会在其中介绍替代方案。
在启动时运行服务
在 Windows 10 下,仍然没有很好的方法来处理这个问题。当然,WSL 发行版并不真正“启动”,但它确实有一个定义的“第一次启动”,您可能希望在其中运行某些东西。
在 Windows 10 下,最好的办法是手动启动服务或通过用户启动文件(例如
~/.bashrc
)运行它们。有关这方面的一些想法,请参阅此答案。但听起来你在 Windows 11 上(因为你提到了 WSLg),在这种情况下,有一个功能允许你指定一个命令(或一系列命令)在分发启动时运行一次。同样,请参阅此答案以获取有关如何配置的信息。
在启动时运行进程管理器
使用这些技术,完全可以运行您想要的任何进程管理器,只要它不需要它是 PID1。
到目前为止我在 WSL 上尝试过的一些方法:
s6 和 dinit 都倾向于认为它们(自然而然地)在物理/虚拟机上运行,因此它们尝试进行一些在 WSL 下不必要的启动。我已经能够删除不必要的项目,然后 dinit 至少运行得很好。不过,我还没有将这些内容整合到可供其他人使用的可重复说明中。
运行系统
甚至可以通过伪装来运行 Systemd,使其在 WSL2(但不是 WSL1)发行版内的新命名空间中作为 PID1 运行(正如我们所讨论的,它已经在其自己的命名空间中运行)。我个人不一定推荐它,但很多人都这样做。我在这个 AU 答案的结尾处介绍了其中的一些内容,所以我不会在这里重复。
Systemd 实际上是一个相当新的项目,于 2010 年左右开始。在它之前使用过很多其他的:sysvinit、upstart、init-ng、s6、launchd(我认为它曾经有过 Linux 版本)。由于各种原因,一些 Linux 发行版仍然不使用 systemd。
在所有这些中,systemd 是最接近您甚至可以称为“进程管理器”的系统。Linux 实际上根本不依赖进程管理器。任何进程都可以在决定不受控制的情况下直接创建(分叉)一个新的子进程。(确实如此不受控制,以至于当 systemd 开始编写诸如“注销应该杀死你的剩余进程”之类的东西时,战争就发生了。)
systemd 和其他此类程序的真正主要工作只是成为一个服务管理器:自动启动某些特定进程,例如负责显示登录屏幕的守护进程(GDM,agetty),并且有时会在它们崩溃时重新启动它们. 但是一旦你进入登录屏幕,其他一切都可以在没有 systemd/init 参与的情况下发生。
事实上,对于 sysvinit,实际的 init 进程几乎没有做任何事情:它监督的唯一服务是 agetty。从字面上看,其他所有事情都是通过普通的 shell 脚本完成的,这些脚本从未正确地接触过 init。启动服务的命令?外壳脚本。整个初始启动过程?运行更多 shell 脚本的 shell 脚本。
因此,对于 WSL 之类的东西,它不想表现得像一个完整的系统(它不应该像一个在使用前必须启动的完整 VM;启动 WSL 意味着即时,就好像你真的在运行 Linux 应用程序一样在 Windows 上),初始化过程可以相当少。我真的不知道 WSL2 使用什么,但它可以是完全自定义的。
(对于 WSL1,甚至可能没有init进程,因为 WSL1 甚至不是 VM,而只是仍然直接在 Windows 上运行的特殊进程的集合。)
WSL 2 有一个自定义的初始化系统,它不是开源的(至少我还没有找到源代码)。
ps
您可以使用或之类的工具查看其流程htop
。它是一个多调用二进制文件,至少执行以下操作:
您看不到所有这些进程/守护进程,因为有些进程/守护进程在所有 WSL 2 容器之外运行(在根命名空间中)。
不使用分发中可能存在或不存在的任何 init 系统。相反,shell 是使用配置的用户 ID 直接生成的。
Systemd 不是 Linux 的固有部分;许多 Linux 发行版不使用它。WSL 将运行您安装的 Linux 发行版使用的任何内容。