WSL2支持systemctl命令

背景

微软官方推出Windows Terminal第一时间,我就安装了这个终端软件。现在GitHub已经有86.8k星,且发布了86个版本。我会将它与WSL以及Linux发行版结合使用,在Windows系统下搭建Linux开发环境。很多Linux发行版都是使用systemd来管理程序进程,但是在WSL中默认是用init来管理进程的,所以为了符合自己的使用习惯,且省去不必要的学习成本,就在WSL的发行版(我这里安装的是Ubuntu22.04)中支持systemd,也就可以使用systemctl命令来启停进程。

相关知识

能够支持使用systemctl命令,提供完整 systemd 的项目有很多:

这些项目的核心原理并无大异,无非是细节处理的好坏和附加功能的多少,但最重要的一点可能是工作层次不同。

Pasted image 20220606151803

前三个脚本都工作在图中的 shell 层,要依赖外置命令执行系统调用。genie 工作在 应用程序 层,它使用 C# 编写,通过 shell 执行系统调用,比前三个还多了一层。最后两个虽然也是 应用程序,但它们由 Rust 编写,不经 shell,而直接由 C system call wrapper 执行系统调用,依赖最少,动态链接编译后只有几百 K。

systemd

在较新的Linux系统上,都使用systemd 管理进程,成为系统的第一个进程(PID 等于 1),其他进程都是它的子进程。systemd为系统启动和管理提供了完整的解决方案。它提供了一组命令。字母d是守护进程(daemon)的缩写。

init

WSL2 的发行版均拥有微软提供的 init,它是一种 systemd 的替代方案,不支持 systemctl 命令,

WSL2 本身是由 Windows 负责运行的,因此使用 treeps 命令时会看到根进程不是 systemd,这将导致无法启动 Linux 系统服务的守护进程 (deamon)。

当我们执行 systemctl 命令的时候,会显示出我们的 init system (PID 1) 并非 systemd,而是微软提供的 init

systemctl
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
ps u -q 1
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0    908   592 ?        Sl   10:31   0:00 /init

安装

首先,需要确认你使用的是WSL2版本,可以在PowerShell中执行如下命令查看:

wsl -l -v

image-20230101164832873

如果默认版本是1,可以使用如下命令进行配置,其中<Version>修改成2即可:

wsl --set-default-version <Version>

还可以使用如下方式设置默认的Linux发行版,其中<distro name>替换为要配置的Linux发行版名称。例如,wsl --set-version Ubuntu-20.04 2会将Ubuntu20.04发行版设置为使用WSL2:

wsl --ser-version <distro name> 2

方法一:微软官方支持方法(推荐)

在网上找到很多种支持的方法,最简单的就是微软官方提供的方法,仅需要添加一个配置文件即可。

  1. 在Windows Terminal中打开Ubuntu22.04

  2. /etc目录新建wsl.conf文件,添加如下内容:

    [boot]
    systemd=true
    
  3. 关闭当前Ubuntu窗口

  4. 打开PowerShell命令行,重启WSL实例

    wsl --shutdown
    
  5. 重新在Windows Terminal中打开Ubuntu发行版,输入如下命令检查是否成功:

    systemctl list-unit-files --type=service
    

    image-20230101165818434

方法二:安装daemonize实现

在官方支持systemd之前,我是使用这个方法来实现的。

  1. 安装daemonizefontconfig

    sudo apt install -y fontconfig daemonize
    
  2. 修改/etc/profile,末尾添加如下配置

    SYSTEMD_PID=$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')
    
    if [ -z "$SYSTEMD_PID" ]; then
       sudo /usr/bin/daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
       SYSTEMD_PID=$(ps -ef | grep '/lib/systemd/systemd --system-unit=basic.target$' | grep -v unshare | awk '{print $2}')
    fi
    
    if [ -n "$SYSTEMD_PID" ] && [ "$SYSTEMD_PID" != "1" ]; then
        exec sudo /usr/bin/nsenter -t $SYSTEMD_PID -a su - $LOGNAME
    fi
    
  3. 在文件/etc/sudoers末尾添加如下内容

    %sudo ALL=(ALL) NOPASSWD: /usr/sbin/daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
    %sudo ALL=(ALL) NOPASSWD: /usr/bin/nsenter -t [0-9]* -a su - [a-zA-Z0-9]*
    
  4. 重新加载/etc/profile使新配置生效

    source /etc/profile
    

参考

  1. Systemd support is now available in WSL!

  2. 使用 WSL 在 Windows 上安装 Linux

  3. WSL2开启systemctl命令

  4. WSL2 开启 systemctl 命令简单方法

猜你喜欢

转载自blog.csdn.net/ls0111/article/details/128513930