用vscode remote + wsl在windows上搭建linux开发环境

3,023 阅读1分钟

什么是wsl

WSL是“Windows Subsystem for Linux”的缩写,顾名思义,WSL就是Windows系统的Linux子系统,可以简单的理解为虚拟机。

“子系统”作为系统层的一部分,相较于应用层(虚拟机)会消耗更少的资源,并且与系统锲合度更高。

因为“子系统”依附于“系统”,所以“子系统”会受到一些限制。

安装使用wsl

首先需要在windows上开启wsl功能,步骤如下:

  1. 打开控制面板,将查看方式改为类别,点击卸载程序

  1. 点击启用或关闭 Windows 功能,在弹窗中勾选 适用于 Linux 的 Windows 子系统,点击确定等待安装

  1. 安装完成后重启操作系统

然后就可以通过命令行工具进行wsl的安装、删除、进入等操作。

使用wsl --list --online查看可安装的liunx发行版本。

C:\Users\lulu>wsl --list --online

NAME            FRIENDLY NAME
Ubuntu          Ubuntu
Debian          Debian GNU/Linux
kali-linux      Kali Linux Rolling
openSUSE-42     openSUSE Leap 42
SLES-12         SUSE Linux Enterprise Server v12
Ubuntu-16.04    Ubuntu 16.04 LTS
Ubuntu-18.04    Ubuntu 18.04 LTS
Ubuntu-20.04    Ubuntu 20.04 LTS

使用wsl --install -d [distribution]进行安装。

C:\Users\lulu>wsl --install -d kali-linux

正在下载: Kali Linux Rolling
...                 

使用wsl --list --verbose已安装的版本。

C:\Users\lulu>wsl --list --verbose

  NAME                   STATE           VERSION kali-linux             Stopped         2
* Ubuntu                 Stopped         2

运行Ubuntu。

C:\Users\lulu>wsl --distribution Ubuntu

lulu@DESKTOP-83LRNMQ:~$

这时再打开另一个终端,运行wsl --list --verbose,会发现Ubuntu的状态变为了Running。

C:\Users\lulu>wsl --list --verbose

  NAME                   STATE           VERSION kali-linux             Stopped         2
* Ubuntu                 Running         2

WSL2开启SSH

sudo apt install openssh-server
sudo /etc/init.d/ssh start

开启允许ssh密码登录:

  1. 修改配置文件 /etc/ssh/sshd_config,找到passwordAuthentication项,修改成yes。
  2. 重启服务: sudo /etc/init.d/ssh restart

从局域网访问wsl

由于使用Hyper-V来实现WSL2,使得WSL更像虚拟机,一个能访问本地硬盘的虚拟机。

所以WSL的网络跟虚拟机也很相似,默认情况下,本机是可以访问到wsl的,但是其他主机访问不了WSL,为了让同一个局域网的其他主机可以访问到WSL,主要有两种方式:

  1. 端口转发
  2. 给WSL2开启桥接模式

端口转发

端口转发这种方式有一定的限制,因为只能开放少量的端口,多了就不好管理了。

  1. 关闭windows主机的防火墙(这是为了简便,更好的方式是配置防火墙规则)
  2. 使用netsh工具在windows主机做端口转发。

比如,我们的windows主机的IP为192.168.0.5,我们的wsl的IP为172.28.76.230,我们在wsl开启sshd服务,我们希望其他主机能够使用ssh连接到wsl。

在windows主机上用管理员打开命令行窗口,输入以下命令:

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=2222 connectaddress=172.28.76.230 connectport=22

listenaddress:监听地址,0.0.0.0表示监听所有地址,建议用0.0.0.0 listenport:监听端口,指的是本地的端口 connectaddress:需要代理的ip connectport:需要转发的端口

那么在其他主机上,我们就可以通过如下命令访问到wsl的ssh服务:

ssh root@192.168.0.5 -p 2222 # 指定端口为2222

netsh的其他其他操作:

  • netsh interface portproxy show all可以显示所有转发端口:
C:\Windows\system32>netsh interface portproxy show all

侦听 ipv4:                 连接到 ipv4:

地址            端口        地址            端口
--------------- ----------  --------------- ----------
0.0.0.0         2222        172.28.76.230    22
0.0.0.0         14000       192.168.25.1    14000
0.0.0.0         7790        192.168.25.1    7790
  • 如果要删除某一条规则,命令如下:
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=2222
  • 如果要清空列表,使用以下命令:
netsh interface portproxy reset

这里个问题是: wsl每次退出后,再次进入,它的IP会变,这些配置都需要重新来过;所以我们需要固定wsl的IP地址。

端口转发配置

我开启了ssh端口,8000-8005,3000-3005。

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=2222 connectaddress=172.28.76.230 connectport=22

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8000 connectaddress=172.28.76.230 connectport=8000

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8001 connectaddress=172.28.76.230 connectport=8001

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8002 connectaddress=172.28.76.230 connectport=8002
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8003 connectaddress=172.28.76.230 connectport=8003
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8004 connectaddress=172.28.76.230 connectport=8004
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8005 connectaddress=172.28.76.230 connectport=8005


netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3000 connectaddress=172.28.76.230 connectport=3000

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3001 connectaddress=172.28.76.230 connectport=3001

netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3002 connectaddress=172.28.76.230 connectport=3002
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3003 connectaddress=172.28.76.230 connectport=3003
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3004 connectaddress=172.28.76.230 connectport=3004
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=3005 connectaddress=172.28.76.230 connectport=3005

给WSL2开启桥接模式

可以参考: ponder.work/2021/01/02/… 虽然我没有成功。

安装Remote-SSH 并连接 WSL

有好几个Remote相关的插件,Remote-SSH、Remote-WSL、Remote-Container等。

连接 WSL听上去应该使用Remote-WSL,但是我们这里有点不一样,主要有两点:

  1. 我们是远程连接
  2. 用来连接的主机不是windows系统

所以并不满足Remote-WSL的使用要求,我们使用使用更加通用的ssh的方式,Remote-SSH是这个体验非常的方便。

安装之后,在弹出命令下拉菜单中选择 Remote-SSH: Add New SSH Host ..

20211109202146

接下来的使用就比较简单,我就不详细描述了。

Remote-SSH操作远程主机(不管是物理机、虚拟机、wsl、container)都非常的方便,可以在编辑代码,打开的终端也是远程的终端。

固定wsl的IP

我们知道wsl2是基于hyper-v的虚拟机,每次重新启动的时候,都会重新拉一个新的hyper-v虚拟机实例,然后虚拟网卡的IP是dhcp随机分配的。

默认的网络模型是,有一个虚拟机交换vEthernet (WSL),wsl实例都连接在这个虚拟机交换上,类似于vmware中的nat网络模式;虚拟机交换其实可以理解为家用路由器,wsl实例的网关为虚拟机交换vEthernet (WSL)的IP。

每次windows重新启动时,都会重新创建vEthernet (WSL),所以vEthernet (WSL)的IP在windows重新启动后也会改变。

我在网上搜索了一下,找到一个方式,使用bat脚本把wsl拉起来,修改wsl的ip,并且修改vEthernet (WSL)的ip。

@echo off

:: 先停掉可能在跑的wsl实例
wsl -d Ubuntu --shutdown

:: 重新拉起来,并且用root的身份,启动ssh服务
wsl -d Ubuntu -u root service ssh start

:: 清除网卡原ip
wsl -d Ubuntu -u root ip addr flush dev eth0
:: 添加新ip
wsl -d Ubuntu -u root ip addr add 172.28.76.230/20 dev eth0
:: 清除原默认路由
wsl -d Ubuntu -u root ip route delete default
:: 添加默认路由
wsl -d Ubuntu -u root ip route add default via 172.28.65.1 dev eth0

:: 是虚拟机交换机,虚拟机交换机其实可以看成家用路由器
netsh interface ip add address "vEthernet (WSL)" 172.28.65.1 255.255.240.0


wsl -d Ubuntu

将文件存为wsl.bat脚本文件,然后“以管理员身份运行”。

修复DNS解析

系统会自动修改/etc/resolv.conf文件。

为了防止WSL2覆盖DNS配置文件,我们新建/etc/wsl.conf。

[network]
generateResolvConf = false

编辑/etc/resolv.conf, 清除原配置,添加以下内容:

nameserver 172.28.65.1

到这里,我们就可以使用vscode的Remote-ssh远程连接到wsl上了。

配置Ubuntu

以下是我在Ubuntu的一下配置,与本主题无关,为了更好的使用,做的一些简单的配置。

备注: Ubuntu的版本为20.4

更新apt镜像地址,以获取更快的下载速度

  1. 原文件备份
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
  1. 编辑源列表文件
sudo vi /etc/apt/sources.list
  1. 替换镜像源

阿里源

deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security multiverse
  1. 更新
sudo apt-get update

安装 zsh 和 oh-my-zsh

  1. 安装zsh、curl、git
sudo apt-get install zsh curl git
  1. 下载安装 oh-my-zsh
sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

下载完成后,根据提示进行操作完成后,默认的 shell 会从 bash 修改为 zsh,如果下次启动 Ubuntu 后,默认 shell 还是 bash 可以通过以下命令手动修改默认 shell

cat /etc/shells #查看所有shell
chsh -s /bin/zsh #设置zsh为默认shell