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

扫描二维码关注公众号,回复: 15510173 查看本文章
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