🚀 2023.06.23 脚本仓库 yunsii/WSL 终于折腾出来了,欢迎体验测试。
此前因为工作的原因,用过一年多 Macbook,还是没有太习惯,在此之前就尝试过了 WSL 作为主力开发系统,对比之下基于 Windows 生态的 WSL 更令人满意,也更游刃有余。刚好最近也重新搭建过一遍开发环境,此前一直想写个脚本做这种事儿,一直没能走出第一步,趁着还有些印象,好好梳理一下自己的开发环境,方便之后写脚本,也算是 WSL 的安利文章了。
由于自己主要从事前端工作,所以开发环境主要偏前端。另外本篇文章所涉及 WSL 默认为 WSL 2,WSL 1 与 WSL 2 对比,请戳这里。
🤔 为什么选择 WSL?
大学时候在同学的介绍下了解到 Linux 这个系统,当时就动手安装过各种发行版,也了解到各个版本之间可能还存在较大差异。深入一点使用过的只有 Ubuntu 和 Deepin,算是一个系列了,还在 Deepin 上学过鸟哥的 Linux 私房菜呢 (´・_・`)
此外还动手搞过双系统,但是始终要关机切到另一个系统,实在过于麻烦了,从而导致三分钟热度一过,Linux 系统就吃灰了。在 Windows 安装虚拟机的方式感觉也不够优雅,对于 Linux 的使用可以说是蜻蜓点水了 _(:з」∠)_ 不过还是有一点收获的,相比于 Windows,Linux 的软件源管理可以很方便的管理各种软件,给我留下很深的印象。后来虽然了解到 Windows 也有这种命令行工具,但至今都还没用过。
直到听闻 WSL 的消息(来源想不起来了),这不是我最理想的使用方式吗?立马安排上了,虽然那时候还是 WSL 1,但是一番体验下来感觉还真不错,开发环境也逐渐过渡到 WSL 1 上了,虽然或多或少会有些小问题,但都是可以 workaround 的,问题不大。现在过渡到 WSL 2 上虽然网络问题折磨得我死去活来,但为了不轻易放弃这种理想的开发体验,克服重重困难解决了碰到的各种奇怪问题,现在可以说是“游刃有余”了。
此外作为程序员不了解 Linux 实在说不过去,虽然现在也只是轻度使用,但是 Linux 给人的感受就是丝滑,不禁想起之前 Windows 装环境的各种折磨实在是痛心疾首。不过现在看起来结合 VS Code,可能只有 JS 的开发体验最好?之前简单尝试过 Python 开发,有点难受。
🌱 准备工作
网络
由于众所周知的原因,前提自然是需要保证网络通畅,这样才能无痛过渡各种问题~至于怎么搞吧,如果碰到什么网络问题可参考我之前的一篇文章《当一名前端攻城狮把 WSL 作为主力开发系统之后……》,最有效的办法应该还得是软路由,暂时没实操过,没有经验可供分享。
2024.09.01 得益于 Mirrored mode networking 的支持,网络问题上不再那么棘手了,也试用相当长的时间了,这里分享一下我当前的 .wslconfig 配置:
[wsl2] networkingMode=mirrored [experimental] autoMemoryReclaim=gradual sparseVhd=true hostAddressLoopback=true更多配置参考 Main WSL settings 的详细介绍。
WSL
安装 WSL 之后就可以开始配置环境了,这里参照官方文档,在 PowerShell 中执行 wsl --install 即可,注意需要满足系统版本最低要求。此外,通过该命令默认安装的是 Ubuntu,如果需要替换可自行配置。
值得注意的是 WSL 默认是将宿主机的设备名称作为 hostname 的,可预先将 Windows 中设备名称改为自己期望的名称。另外需要注意的是确保 BIOS 中的已启用了虚拟化(virtualization)。
此外有个关于 Hyper-V 的讨论,暂时没遇到。
软件
- Windows Terminal
- VS Code
- Git
- Chrome
- Firefox Developer Edition
- Windows PowerToys
- Ditto
- Snipaste
- ScreenToGif
- CrystalDiskInfo
- SumatraPDF
子系统安装过程中,可提前将上述软件安装完成。Windows Terminal 和 Windows PowerToys 可在微软应用商店中安装,如果无法访问微软应用商店或者想尝试软件预览版,可通过 Windows Terminal Releases 和 Windows PowerToys Releases 下载安装。
另外 Windows Terminal 会自动将子系统添加到配置中,体验相当丝滑 🚀
Git 的安装是以备不时之需,毕竟之后主要的开发任务还是在 WSL,另外是避免在 Windows 上直接使用 VS Code 的时候 Git 相关扩展弹窗报警告信息。
🛠 WSL 开发环境
系统安装完毕,就可以开始正式配置环境了,用户名密码按需配置就好了,我的密码配置得比较简单,方便使用。另外不会有人跟我第一次用 Linux 一样,输入密码的时候以为没有输入进去吧?
_(:з」∠)_
配置 vim
mkdir ~/.vim && vim ~/.vim/vimrc
添加如下配置
" ref: https://stackoverflow.com/a/1878983/8335317
set tabstop=4
set shiftwidth=4
" ref: https://vi.stackexchange.com/a/28017/48038
set softtabstop=4
" 将 tab 转换为 space
set expandtab
" 支持鼠标定位,ref: https://stackoverflow.com/a/28616337/8335317
set mouse=a
换源
备份默认源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
编辑源文件
sudo vim /etc/apt/sources.list
输入 Esc + gg + dG 清空文件内容后替换为如下的中科大源
# ref: https://mirrors.ustc.edu.cn/help/ubuntu.html#id7
# 默认注释了源码仓库,如有需要可自行取消注释
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirrors.ustc.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
# deb-src https://mirrors.ustc.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
换源后更新一下
$ sudo apt-get update
$ sudo apt-get upgrade -y
如果更新时发生异常 apt repository is not signed 可通过添加 [trusted=yes] 解决。
配置 zsh
$ sudo apt-get install zsh -y
# 安装 Oh My Zsh
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# 网络不佳时
$ sh -c "$(curl -fsSL https://raw.fastgit.org/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# 安装完成后会询问是否将 zsh 设置为默认 Shell,默认为是,直接回车即可
# 安装 spaceship 主题
# ref: https://github.com/spaceship-prompt/spaceship-prompt#oh-my-zsh
# 克隆仓库
$ git clone https://github.com/spaceship-prompt/spaceship-prompt.git "$ZSH_CUSTOM/themes/spaceship-prompt" --depth=1
# 符号链接
$ ln -s "$ZSH_CUSTOM/themes/spaceship-prompt/spaceship.zsh-theme" "$ZSH_CUSTOM/themes/spaceship.zsh-theme"
# 设置 ZSH_THEME="spaceship"
$ vim ~/.zshrc
# 安装 zsh-autosuggestions 插件
# ref: https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md#oh-my-zsh
$ git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
# 添加插件到 Oh My Zsh 插件配置 ~/.zshrc 中
# plugins=(
# # 默认插件
# git
# # other plugins...
# zsh-autosuggestions
# )
# 安装 zsh-syntax-highlighting 插件
$ git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
# 添加 zsh-syntax-highlighting 插件启动代码
# Note the `source` command must be **at the end** of `~/.zshrc
# why? https://github.com/zsh-users/zsh-syntax-highlighting#why-must-zsh-syntax-highlightingzsh-be-sourced-at-the-end-of-the-zshrc-file
$ echo "source \$ZSH_CUSTOM/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ${ZDOTDIR:-$HOME}/.zshrc
# 重新配置 zsh
$ source ~/.zshrc
⚠️ 如果终端老是显示三个点,禁用 SPACESHIP_PROMPT_ASYNC
安装 Fira Code 字体
由于 spaceship 主题会使用一些特殊字符,根据 issue git icon broken 可知,需要安装兼容性字体,遂选择安装官方推荐的 Fira Code。
在 Release 下载最新的字体包,解压后进入到 ttf 文件夹全选安装,值得注意的是安装后直接配置对应字体是不生效的,碰到了跟 issue VS Code doesn't recognizes Fira Code 一样的问题,重启电脑后分别在 Windows Terminal 和 VS Code 的集成终端配置对应字体即可。
值得注意的是安装字体时需要为所有用户安装,避免 Installed fonts disappearing after restart 的问题,反复安装了很多次,应该是这个原因。
安装 git
# 先查看系统中是否已安装 git,如果没有再安装
$ sudo apt-get install git
$ git --version
$ 配置 core.editer,VS Code 结合插件生态可以很方便的编辑
$ git config --global core.editor "code --wait"
Zsh 默认安装 git 插件,使用方式参考 aliases。
安装 nvm
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
安装 node
默认安装最新版即可。
$ nvm install --lts node
$ node --version
# 切换默认 node 版本
$ nvm alias default 18
如果 nvm 下载 Node 太慢了,可尝试修改 Node 镜像源,与此同时 npm 镜像源也可尝试修改:
$ export NVM_NODEJS_ORG_MIRROR=https://mirrors.ustc.edu.cn/node/
# ~/.npmrc
registry=https://registry.npmmirror.com
⚠️ 在 nvm 安装后重启终端试试,看看 nvm 的相关配置是否会显著提升终端启动时间,如果有影响,可配置 nvm 的懒加载,也可尝试使用 zsh-nvm 插件。
# 如果安装了多个子系统可通过该命令查看
$ wsl --list
# 通过如下命令选择特定子系统进入
$ wsl -d <Distro>
启用 corepack
可通过 corepack enable 启用该实验特性,根据文档来看,corepack 在 Node.js v16.9.0 和 v14.19.0 开始就可用了。
安装 ni
妈妈再也不用担心我纠结包管理器了。
$ npm i -g @antfu/ni
有了 ni 之后,可在 .zshrc 中添加以下命令别名:
# -------------------------------- #
# Node Package Manager
# -------------------------------- #
# https://github.com/antfu/ni
alias nio="ni --prefer-offline"
alias s="nr start"
alias d="nr dev"
alias b="nr build"
alias bw="nr build --watch"
alias t="nr test"
alias tu="nr test -u"
alias tw="nr test --watch"
alias w="nr watch"
alias p="nr play"
alias c="nr typecheck"
alias lint="nr lint"
alias lintf="nr lint --fix"
alias release="nr release"
alias re="nr release"
其他值得推荐的库
安装 Java
由于最近使用到的 npm 包会用到 Java,所以将 Java 也作为工具之一了。
$ sudo apt install openjdk-8-jdk
$ java --version
也可以不直接安装,后来自己无聊折腾了一个自动安装 JRE 的库 node-jre-extra,如果有需要欢迎试用 😂
迁移子系统
由于默认 WSL 将子系统都安装在系统盘,在系统配置完成后最好再做一次迁移,避免随着时间的积累系统盘直接爆表再迁移就很难受了。可根据该回答 Move WSL (Bash on Windows) root filesystem to another hard drive? 手动迁移,顺便还做了一个子系统的纯净版镜像,如果有需要可随时恢复,不亏 😂
此外 import 安装后如果启动系统没有进入之前设置的默认用户,可参考 Change default WSL 2 user after export/import 重新设置一下。
不过当前个人电脑是将 Windows 和 WSL 都装在一个固态盘内。
配置 VS Code
最后就到了 VS Code 配置环节,万事俱备的情况下,直接运行 code 命令打开 VS Code,由于第一次通过远程调用的方式打开,在经过简单的初始化之后一切就准备就绪了。
个人主题相关配置
{
"workbench.colorTheme": "Vitesse Light Soft",
"editor.fontFamily": "Fira Code Retina, Consolas, monospace",
"terminal.integrated.fontFamily": "Fira Code Retina, Consolas, monospace",
"terminal.integrated.fontSize": 12
}
推荐扩展
- Auto Rename Tag
- Material Icon Theme
- ESLint
- Git Graph
- GitLens
- indent-rainbow
- Path Intellisense
- SVG
- YAML
- Code Spell Checker
- CSS Modules
- CSS Peek
- DotENV
- Color Highlight
- Thunder Client
- Links
WSL 使用命令
查看 WSL 安装目录
网络位置
\\wsl$
实际安装目录
Get-ChildItem "HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss" -Recurse
🦄 进阶
以上只是完善了个人的开发体验,最近的实践下来还需要考虑团队协作的便利性,因此又打算增补一部分进阶的内容。
Windows 文件共享
目前以 Windows 11 文件共享为例。
启用 Guest 帐户
帐户与账户,傻傻分不清楚
运行 gpedit.msc 启用来宾帐户

其次,从“拒绝从网络访问这台计算机”中移除 Guest 帐户

这样我们就能通过 Guest 访问共享的文件夹了,而不是自己本身的账号,方便其他人使用。
添加共享文件夹
共享文件夹配置,通过属性进入文件夹的共享选项卡

点击共享按钮,将 Everyone 添加到共享用户后保存即可分享该文件夹,结果如下图

访问共享文件夹
网络设置中允许其他人访问共享文件,可根据实际情况自行调整

通过 ipconfig 查看本机 IP,假设为 192.168.0.123。用户可在文件管理器中输入 \\192.168.0.123 查看本机所有的共享文件夹。如果是其他设备,可尝试 smb://192.168.0.123 访问。
注意:请配置合理的用户访问权限。
SSH 连接 WSL
特殊情况下可能需要方便其他开发者连接我们的 WSL 做些操作,为此不得不解决这个问题。
创建新用户
创建 guest 用户并添加到个人用户所属的分组,假设我们创建的个人用户为 yuns。
$ sudo useradd -m guest
# 创建 guest 用户密码,方便起见与用户名相同
$ sudo passwd guest
# 将用户 guest 添加到 yuns 分组,方便权限管理
$ sudo usermod -a -G yuns guest
当然,为了方便 guest 用户,最好还是配置默认使用 zsh 终端,不然默认终端用起来太难受了。
SSH 服务器
首先需要为 WSL 开启 systemd 功能,记得重启 WSL。
# 启动
$ sudo systemctl start sshd.service
# 停止
$ sudo systemctl stop sshd.service
# 重启,修改 sshd 配置需要重启服务
$ sudo systemctl restart sshd.service
下次 WSL 启动时自动启动
$ sudo systemctl enable sshd.service
根据这个说法,如果报错可尝试 sudo systemctl enable ssh.service,我是使用的系统自带的 SSH 服务器,使用这个命令后看起来正常了,如果还有问题大概需要安装 openssh-server 来代替默认的 SSH 服务了。
配置完成后在 WSL 内可通过 ssh yuns@localhost 看看是否能正常连接。
本地 SSH 登录
准备就绪后就可以尝试 SSH 登录我们的 guest 用户了,为了方便我决定采用密钥登录的方式,避免每次都需要密码验证。可以直接在 Windows 侧 PowerShell 中调用 ssh-keygen 初始化密钥。将生成的 SSH 公钥手动上传到 WSL 下的 /home/guest/.ssh/authorized_keys 文件中,文件结尾注意需要有换行。
当然,由于没有在 Windows 上找到 ssh-copy-id 的平替,手动上传显然太低级了,因此,我们可以通过 WSL 的 ssh-copy-id 命令来上传我们在 Windows 侧的 SSH 公钥,因为默认 Windows 硬盘都会被挂载到 WSL 中的。
$ ssh-copy-id -i /mnt/c/Users/YourUsername/.ssh/id_rsa.pub guest@localhost
默认为 rsa 密钥,请选择正确的公钥文件。更多细节可参考阮一峰老师的 SSH 教程。
配置好 authorized_keys 后,先在 PowerShell 中通过 wsl -d "DistributionName" hostname -I 拿到 WSL 的 IP,假设为 172.23.240.97,再次在 PowerShell 中尝试 ssh guest@172.23.240.97 看看是否能正常连接。需要注意的是确保 guest 用户添加已被添加到 sshd 的 AllowUsers 配置中。
一切顺利的情况下就来到最后的关键步骤了,Windows 侧的端口转发。
$ netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=22 connectaddress=172.23.240.97 connectport=22
# 查看端口转发
$ netsh interface portproxy show v4tov4
更多操作参考 netsh.txt
当这一步正常时我们就能通过 Windows 的本地 IP 比如 192.168.0.123/localhost/127.0.0.1 来实现 SSH 登录了,看看 ssh guest@192.168.0.123 是否成功登录。
局域网内 SSH 登录
值得注意的是,如果 WSL 的 IP 会变化还需要添加额外处理,参考 Enable SSH Access to WSL from a Remote Computer 的 Use Task Scheduler to automate the script 部分。
要想让局域网内其他人能够访问我们 22 端口,还需要添加防火墙规则:
$ netsh advfirewall firewall add rule name=”WSL SSH” dir=in action=allow protocol=TCP localport=22
# 查看规则
$ Get-NetFirewallPortFilter | Where-Object { $_.LocalPort -eq 22 } | Get-NetFirewallRule
最后,如果 sshd 允许密码登录此时我们就可以禁用密码登录了,记得让需要登录的用户提供其 SSH 公钥,我们将其添加到 /home/guest/.ssh/authorized_keys 中就能打通整个流程了。
# /etc/ssh/sshd_config
AllowUsers yuns guest
PasswordAuthentication no
参考资料
- SSH 教程
- Enable SSH Access to WSL from a Remote Computer
- Is there a whoami to find the current group I'm logged in as?
- Reload a Linux user's group assignments without logging out
以上功能配置完成,可利用的场景为其他开发者可通过 SSH 连接到本机的 WSL 环境调用我们写好的脚本编译项目,并将编译后的项目复制到 Windows 的共享文件夹下,方便非开发人员测试生产环境的项目。