Contents

WSL2 Systemd问题

0.阅读须知

阅读和操作本篇文章需要掌握或者熟悉一下技能树:

01.已经可以独立安装wsl2子系统;

02.知道一些简单的Linux操作指令,Vim,ssh证书登陆等操作熟练

03.已将安装了LxRunOffline和Windows Terminal以及SSH连接工具

1.基础环境部署

Windows10 20H2以上系统,并且已经启用或者安装了wsl2子系统;

1.1前言:

wsl2子系统或者wsl子系统都是在微软提供的内核下运行其它发行版的系统,这个和Docker的工作原理很像,Docker是和宿主机共享内核的情况下进行工作的,所以,原则上讲,我们采用Linux各大发行版的Docker镜像+wsl2的内核就可以自定义专属我们的Linux子系统了。

首先瞧一眼这个链接,里面的各大发行版都躺在这里等待我们发掘,

https://github.com/docker-library/official-images/tree/master/library

1.2.Centos

1.2.1下载

其实微软商店里面提供了Ubuntu和Debian以及Suse的发行版,但是Centos的发行版是个人提供的,好像还收费,之前很多人也是从Github上查找Centos的发行版的,有些牛人打包了成品,还提供了exe安装包,感谢他们。但是这次咱们从官方的镜像入手,Centos镜像地址如下:

https://github.com/docker-library/official-images/blob/master/library/centos

里面最上面那个repo就是镜像的地址:

GitRepo: https://github.com/CentOS/sig-cloud-instance-images.git

点进去之后,由于Centos6和Centos8(提前被毙了,坐等Rock Linux)都死了,还是选择Centos7吧,点开master分支定位到最新的7.8.2003版本,里面那个tar.xz 就是咱们的目标了,冲啊。。。

https://github.com/CentOS/sig-cloud-instance-images/tree/CentOS-7.8.2003-x86_64/docker

https://github.com/CentOS/sig-cloud-instance-images/blob/CentOS-7.8.2003-x86_64/docker/centos-7.8.2003-x86_64-docker.tar.xz

这个玩意下载到本地,通过LxRunOffline就可以部署了,命令如下:

1
2
3
4
5
6
7
8
#部署
LxRunOffline.exe install -n wsl-centos7 -d E:\data\wsl\sys\wsl-centos7 -f  E:\down\centos-7.8.2003-x86_64-docker.tar.xz
#转换为wls2
wsl --set-version wsl-centos7 2
#设置为默认
wsl -s wsl-centos7
#查看
wsl -l -v
1.2.2优化准备

其实到这一步我们已经将Centos安装好了,但是每次都需要手动启动比较烦,当然也可以通过Windows Terminal启动(下拉的箭头自动回识别所有的发行版,巨硬的全家桶就是好用),但是这个不是我们想要的,我这里采用的新建一个bat脚本加入开机启动的(Windows计划任务),脚本内容如下:

1
2
3
wsl -d wsl-centos7 -u root ip addr add 192.168.88.70/24 broadcast 192.168.88.255 dev eth0 label eth0:0
netsh interface ip add address "vEthernet (WSL)" 192.168.88.188 255.255.255.0
start E:\data\wsl\start\wsl-centos7.vbs

里面做了一下3件事情,wsl的虚拟网卡增加ip,wsl2 子系统增加ip,和启动自定义的脚本,有了固定ip,我们就可以写死hosts了,比如做个hosts映射至xxx.a.com,看着也挺唬人的;

wsl-centos7.vbs内容如下:

1
2
Set ws = CreateObject("Wscript.Shell")
ws.run "wsl -d wsl-centos7 -u root /etc/init.wsl start", vbhide

这个vbs是启动的是我wsl2子系统的一些脚本,我开机了sshd,cron,elk,以及一些大数据的组件等,这个一会儿在说,其实就是一个systemctl $1 xxx.service的类型,其实新安装的基于Docker的Centos还有个问题,那就是man文档精简了,这个在yum的配置文件改下就行,一会配置国内源和systemctl的时候再说。

1.3Debian地址

Debian11

https://github.com/debuerreotype/docker-debian-artifacts/tree/dist-amd64/bullseye

https://github.com/debuerreotype/docker-debian-artifacts/blob/dist-amd64/bullseye/rootfs.tar.xz

Debian10

https://github.com/debuerreotype/docker-debian-artifacts/tree/dist-amd64/buster

https://github.com/debuerreotype/docker-debian-artifacts/blob/dist-amd64/buster/rootfs.tar.xz

1.4Ubuntu地址

https://partner-images.canonical.com/core/

Ubuntu LTS对应的版本为

dist name
16.04 LTS xenial
18.04 LTS bionic
20.04 LTS focal

截止2021年3月31日rootfs最新的地址如下:

16.04 LTS

https://partner-images.canonical.com/core/xenial/current/ubuntu-xenial-core-cloudimg-amd64-root.tar.gz

18.04 LTS

https://partner-images.canonical.com/core/bionic/current/ubuntu-bionic-core-cloudimg-amd64-root.tar.gz

20.04 LTS

https://partner-images.canonical.com/core/focal/current/ubuntu-focal-core-cloudimg-amd64-root.tar.gz

2.调优开始

这里调优我们基于前面的刚部署好的Centos 7

2.1.wslconfig

首先我们在Windows的用户家目录下新建这个一个东西 .wslconfig:

我的配置如下,可以参考:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[wsl2]
localhostForwarding=true

swap=0
[network]
# 解决域名解析失败的问题
generateResolvConf = false 

#将WSL 2中的VM内存限制为4 GB
memory=4GB 

#使WSL 2 VM使用两个虚拟处理器
processors=2 

更详细的配置见:https://docs.microsoft.com/zh-cn/windows/wsl/wsl-config#configure-global-options-with-wslconfig

最下面的wsl2设置。

2.2 /etc/wsl.conf

这个文件是在虚拟机装创建的,当然也可以在Windows创建以后cp至虚拟机中,因为所有的Windows磁盘会挂载至虚拟机的/mnt/目录内:

我的配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#  /etc/wsl.conf 
[automount]
enabled = true
root = /mnt/
options = "uid=1002;gid=1002,metadata,umask=22,fmask=111"
mountFsTab = true
[filesystem]
umask = 022
[network]
generateResolvConf = false
[user]
default=forsre

上面那个uid和git是我自定义用户forsre的值,如下为了写入读取Windows中的文件权限方便些,当然,单独用root用户也很美很暴力:

1
2
#id forsre
uid=1002(forsre) gid=1002(forsre) groups=1002(forsre),1003(docker)

其中我取消了自动生成的域名解析文件,我自定定义的 /etc/resolv.conf nameserver 223.5.5.5 nameserver 223.6.6.6

更详细的配置见:https://docs.microsoft.com/zh-cn/windows/wsl/wsl-config#configure-per-distro-launch-settings-with-wslconf

例如:

2.3 man

配置国内源,略,从我的博客地址里面随便找个进行配置就行,配置base和epel就够了

默认从Docker安装的Centos是取消man文档的,这时候我们需要/etc/yum.conf 中注释掉:

tsflags=nodocs

然后把所有已经安装的组件重新安装下:

rpm -qa | xargs yum reinstall -y

注意:Debian和Ubuntu也会有文档这个问题,解决方案是注释掉 (或者删除此文件,不推荐)/etc/dpkg/dpkg.cfg.d/excludes里面所有的path-exclude的部分,然后执行:

dpkg -l | grep ^ii | cut -d' ' -f3 | xargs apt-get install -y --reinstall

2.4 systemd

systemd这个玩意一直被争论最多,很容易撕逼,Docker就和这货争论已久,之前Debian曾经也放话启用systemd组件,但是从upstart,sysv过来的人其实发现systemd还是简化了很多之前的/etc/init.d/下面的启动脚本的,当然要是只用service脚本启动的话,此时,这个环境已经基本ok了,自己配置一个sshd,随便从Centos6找一个/etc/init.d/sshd脚本改下就能用了。但是我之前太多脚本都是systemd的,不想重写了,就找到了一个systemd的解决方案。

Docker中解决systemd是采用的init赋权的方式的进行的,

docker run -tdi --privileged=true centos /usr/sbin/init

而wsl2是通过微软的hyper-v启动的,启动的的时候可操作性小,搜遍各大论坛,我找打了目前个人感觉最方便的一种方式,参见这个大叔的脚本:

https://github.com/gdraheim/docker-systemctl-replacement

在虚拟机内执行

1
2
3
4
5
wget https://raw.githubusercontent.com/gdraheim/docker-systemctl-replacement/master/files/docker/systemctl.py

mv /usr/bin/systemctl{,.bak}

cp systemctl.py /usr/bin/systemctl && chmod +x /usr/bin/systemctl

就可以完整的执行systemctl了,使用至今只发现一些小问题,如果执行systemctl报错的话,可以使用-vvv参数,一般都是pid文件位置的问题,重新改下相关的systemd启动文件的pid的位置即可,一般系统的systemd的启动脚本位于/lib/systemd/system/。

接下来编辑之前的那个vbs调用的那个启动脚本即可,,例如:

1
2
3
#/etc/init.wsl 
#! /bin/sh
systemctl $1 sshd crond rsyslog

配置上zsh和基本的环境(Golang,Node,Java,Python,Conda就可以愉快的coding了)

2.5 k8s

安装Docker Desktop,并且启用k8s,可以参考阿里的加速脚本,国内会容易些。

另外Docker的wsl2默认位置在C盘,可以将其移走至其它磁盘(移动期间请保持所有的wsl2进程关闭,wsl -l -v查看,关闭所有wsl2的命令为wsl –shutdown),例如:

1
2
LxRunOffline.exe move -n docker-desktop -d e:\data\wsl\sys\docker-desktop
LxRunOffline.exe move -n docker-desktop-data -d e:\data\wsl\sys\docker-desktop-data

至此,定制的wsl2基本可以用了,设置一个开机启动项即可。

2.6 tcp透传

默认情况下wsl2不能从外部访问,但是可以做tcp映射,cmd管理员下,如下:

1
2
3
4
5
#enable
netsh interface portproxy add v4tov4 listenport=8080 connectaddress=192.168.8.88 connectport=51200 listenaddress=* protocol=tcp

#disable
netsh interface portproxy delete v4tov4 listenport=8080 protocol=tcp

这样就可以访问局域网的8080转发至wsl2的8080了。

2.7 多wsl2机器

加入启动多台wsl2机器,需要启动不通的ssh端口来区分,因为这些机器都是共享一个hyper-v IP的,详见

根据下面的评论可知,可以使用不同的端口进行区分,或者使用不同的namespace,详见

3.有啥疑问可以邮件我,如果我能解答的话。。。

forsre@foxmail.com