我如何用 Windows 开发 —— 2021 我的开发环境

由于搭载 macOS 的设备越来越昂贵且槽点颇多,加上微软近些年开始发力开发者体验,我的工作环境已经从 MacBook 切换到了运行 Windows 系统的非苹果机器。这是多方面因素决定的:平时玩的游戏需要在 Windows 上运行,桌面环境也是 Windows 的比较舒适耐用。

使用 Windows 进行开发工作虽说并不像在 macOS 上那样可以使用诸多 POSIX 标准的工具,但鉴于硬件性能的提升和虚拟化技术的成熟,使用虚拟机或者 WSL2 也未必是不可接受的方案。此外,随着 Visual Studio Code 的 Remote 功能越发完善,在 Windows 的窗口环境下享受和 Linux 一样的开发体验也并非不可能。

当然,使用 Windows 开发完全是个人选择;本文并不打算讨论 Windows 对比其它操作系统的优劣,只是在此简单介绍我如何在 Windows 桌面上进行我的开发工作,希望对因为种种原因选择使用 Windows 工作的读者能有所启发。

需求

在讨论开发环境之前,我们首先得讨论开发的需求是什么。我个人写的东西还挺杂的,大部分时候使用 Visual Studio Code 写 TypeScript, JavaScript 和 PHP。除此之外,我有时候会使用 Android Studio 写 Java/Kotlin,或者用 Goland 写 Go,又或者使用 Visual Studio 2019 写 C#。此外,我还需要运行 DataGrip 之类的数据库管理软件、kubectl 之类的集群管理软件,还需要使用 ssh 登录数台远程主机。我的个人项目几乎都使用 docker 进行部署,因此 docker 也必不可少。

总体来说,我需要:

  • Visual Studio Code
  • Visual Studio
  • JetBrains IDE,包括:
    • Android Studio
    • Goland
    • DataGrip
  • 终端、zsh
  • docker

了解了自己的需求之后,就能根据自己的需求来考察选项。

OS

如标题所述,我的宿主机基本上是 Windows 操作系统,一般是最新的 Release 或者 Beta 版本,比如在写作文章的时候是 Windows 11 (Pro) Insider Beta。这目前是为了使用 wslg,在 Windows 11 正式发布之后我多半会切换到稳定版上。

鉴于平日打交道的服务器多半是 Debian 或者 Ubuntu 这类 Linux 发行版,本地开发环境上有一个 Linux 的机器很重要,我称之为 Linux dev box。在这个 Linux dev box 内的操作系统上,我选择使用 ArchWSL 提供的 ArchLinux 镜像作为日常的 dev box 使用,这主要是考虑到 ArchLinux 的软件包比较新,而且 AUR 上有很多方便的包可以选择使用。在非生产环境下,使用 ArchLinux 的体验还是不错的。

虚拟化

Linux dev box – WSL2

在 Windows 宿主机上运行 Linux box 是很简单的事情,而且你有诸多选择:以 VirtualBox 为代表的虚拟机方案;WSL1;WSL2。我的选项是 WSL2,你可能觉得 WSL2 和虚拟机也没什么区别,事实上几乎如此,只是省去了不少自己对虚拟机做的集成配置。WSL1 曾经是我梦想中的方案,但 WSL1 作为日常使用的子系统还是有其种种问题,其环境和物理或者 KVM 虚拟化的 Linux 还是有所区别,IO 也令人发指。

一个比较常见的问题是 systemd,众所周知 WSL 不管是 1 还是 2 都不支持直接启用 systemd,大概是因为微软自己启动的缘故。虽然没有官方的支持,但使用 genie 提供的 bottled 方案也并不是一个很难接受的选择,事实上体验基本与 systemd 一致——当然如果你需要的某些复杂高级功能工作不正常,那当我没说。听说 wsl2-hacks 也是个办法,但我没有尝试过。

另外,由于微软的奇葩设计,在每次 Windows 启动的时候 WSL2 都会被随机分配到完全随机的网段,这会导致不少问题。我遇到的主要是 Windows 下的防火墙难以配置WSL2 内连宿主机 IP 不稳定;还有选到和 docker 等虚拟环境冲突的网段导致路由错乱。前两个问题我通过一些脚本来解决,我把他们放到了 GitHub 的 oott123/work-on-windows 上供读者参考;而最后一个问题我也通过了一些办法解决,后文提到 docker 的时候再仔细说。

用上 WSL2 之后,wslg 也变得很简单,只需要 export DISPLAY=:0 并且 export WAYLAND_DISPLAY=wayland-0 就可以让 Linux 桌面程序显示成 Windows 窗口了。不过在我这边,wslg 的剪贴板不一定工作,我找到了一个 issue,但看起来没什么帮助的样子。之后也许要尝试自己去做剪贴板同步了。

如果你不想使用 Insider 系统来启用 wslg,也可以试试第三方方案 X410 。X410 ( X for 10 ) 是一款商业化的 X Server,相比 VcXserv 有更好的 HiDPI 支持,同时体验也更加流畅。官网有一些非常详尽的教程,例如和 WSL2 配合使用的和 Hyper-V 配合使用的,都可以看看。

Windows dev box – Windows 10

基于某种“不想在宿主机上安装开发环境”的奇怪洁癖矫情,我没有在我的宿主机器上安装 Visual Studio 、Android Studio 等开发环境,而是选择使用 VMWare 创建了一个虚拟机,并在虚拟机内安装。这台虚拟机里安装了 Visual Studio、Windows SDK、Android Studio 和 Visual Studio Code 等等 IDE 或编辑器。

因为使用频率比较低,所以也没咋配置,直接用 VMWare 开干了。实际体验只能说尚可接受,操作起来还是偶有迟滞的感觉,反正用得不多,懒得管了。

开发环境

IDE / SDK

鉴于我有两个 dev box ,那么某个 IDE 或者环境该在哪个 box 里安装无疑成了需要选择的事情。目前,我的基本准则是,能在 WSL2 里安装的,都在 WSL2 里安装:

  • Visual Studio – 宇宙第一 IDE 只支持 Windows,所以在 Windows box 里安装
  • Android Studio – WSL2 连实体机不方便,所以在 Windows box 里安装
  • Goland / DataGrip – WSL2 里安装,wslg 使用
  • Sublime Merge – WSL2 里安装,wslg 使用
  • nodejs, yarn, php 等命令行开发环境 – WSL2 里安装

Visual Studio Code

Visual Studio Code 的 Remote 功能是本世纪以来最伟大的发明。
—— 三三・自己说的

早在 coder 发布 code-server 的时候,我就搭建了一套用于日常开发;后来 vscode 发布了官方支持的 Remote 功能之后,我也就随之迁移到了 Remote 上进行开发。之前还需要通勤的时候,无论在公司还是在家里,都可以用 vscode remote 连接到自己的服务器摸一些东西;现在的话主要用于在 Windows 上连接 WSL 开发。

显然,我的 Visual Studio Code 是安装在宿主机上的;但使用体验和安装在 Linux 上并没有什么分别,一切都很顺滑。

Windows Terminal

我平时使用 Windows Terminal 作为我的 shell,大概配置成这个样子:

这张图片展示了使用 Windows Terminal 连接 WSL2 运行 neofetch 的结果。

在 Windows Terminal 中,为 WSL2 的 Profile 设置开始路径为 \\wsl$\Arch\home\oott123 这样的目录,就可以实现打开新标签的时候切换到 WSL 的家目录了,在这里就可以方便地存放自己的代码和开发环境了。注意不要把代码放到 /mnt/c/ 之类的地方去,否则你的 IO 会很惨。我平时使用 zsh 作为默认 shell,在 WSL2 里也是能直接使用的,就和普通的 Linux 系统没什么区别了。

另外,我使用了修改过的 zsh-notify 插件,配合 BurntToast实现命令错误/长时间任务完成推送 Windows 通知的功能。虽然由于偷懒,没有去检测当前焦点窗口是否在 shell 中导致命令报错的时候稍微有点吵之外,其实还挺好用的。

Docker

在 WSL2 里安装 docker 也是一件有两个选择的事情:使用 Docker Desktop,或者直接安装 docker daemon。我曾经选择了前者,还用上了非常酷炫和魔法的 WSL2 daemon,直到它出现了不少问题,最后由于我的 Arch 内核太新出现了一个我修不好的问题,一气之下就把它整个删掉了,安装了正常的 docker daemon。

前文提到过,WSL2 启动的时候会随机选择网段,有时候会选到和 docker 等虚拟环境冲突的网段导致路由错乱。后来我在 Windows 内创建一个和 docker 同网段的虚拟网卡之后,Hyper-V 似乎就很聪明地避开了这个网段,问题得以解决。

打开设备管理器,选择操作-添加过时硬件,依次选择安装手动从列表选择的硬件、网络适配器、Microsoft、Microsoft KM-TEST,并确认即可
使用设备管理器添加 KM-TEST 虚拟网卡

体验

在 Microsoft 大力拥抱开源社区的今天,使用 Windows 作为开发环境已经不是令人难以接受的事情了——当然前提是你使用 WSL2,我不会真的在 Windows 这样的 OS 上做开发的。微软的 Windows 虽然从来都广受诟病,但它的桌面环境体验不是其它竞争者(是的,我是说 Linux。你说什么 m 什么 OS 是啥,我听不见)可以比拟的。如果说曾经基于 BSD 内核的 macOS 拥有类似 UNIX 的开发体验,那么 WSL2 则是 99.9% 的 Linux 开发体验,这对于我来说是非常重要且舒适的。是的,绝对不是因为我要用 Windows 打游戏。

因为基于虚拟机的 dev box 使得备份和迁移变得异常方便,全虚拟化环境的拟真也能带来许多优势,而 WSL2 和 Windows 的集成也足够顺滑,所以我想,在可以预见的将来,我的开发环境仍然会首选宿主机 Windows + Linux / Windows dev box 的模式来配置。

在 Windows 下使用 boot2docker 搭建 docker 开发环境

很久以前研究过一会儿 docker ,当时觉得只是一个轻量级的虚拟机包装而已,没觉得有多大用。

最近发现这玩意还蛮好玩的,但是又懒得翻以前的虚拟机了,于是发现一个叫 boot2docker国内下载(via DaoCloud) 的东西。官方宣称是“It runs completely from RAM, weighs ~27MB and boots in ~5s (YMMV).”。

下载回来的安装包有 100 多 MB,当时在想说好的 27MB 呢,结果发现包里有个 VirtualBox 和一个 msysgit ……简直坑。

如果你的机器上没有这俩玩意,那就放心大胆的直接安装吧。它会帮你把各种琐事配置好,官方的指导文档里也写的十分详细。

如果你的系统里有 VirtualBox 了,那也就直接安装,它会自动识别系统上的 vbox 的,不过你最好先测试一下你的 Host-only 网卡是否正常。

那么重点来了:如果你的系统里有 msysgit,并且还有其它的 GNU 工具链,比如我这种装了 Gow 的人,那么其实这个玩意是有坑的。

要说这个坑,首先要谈一谈 boot2docker 的工作原理。 boot2docker 由 VirualBox 里的一个叫 boot2docker 的虚拟机、一个用来管理 Virual Box 里的虚拟机的工具 boot2docker.exe 和 docker 本体 docker.exe 组成。

当你执行 sh start.sh 的时候,它首先调用 boot2docker init 来创建这个虚拟机(如果已经存在则跳过);其次将该虚拟机启动;最后使用 boot2docker ip 来获取虚拟机的 ip 地址并设置环境变量。

boot2docker ip 这个命令,是调用系统中的 ssh 来获取 ip 地址的。它在 init 的时候,将虚拟机的 22 端口转发到宿主机的 2022 端口,并运行 ssh -p 2022 docker@localhost ip addr show dev eth1 来获取 ip 地址(详细的命令可运行 boot2doker -v ip 来显示)。而 Gow 里的 ssh 指令,则是调用了 PuTTY 的 plink.exe

那么问题来了:plink.exe 根本不支持 -p 语法,也不支持它所使用的 -o 等参数。

所以,如果你装了 Gow,请一定把 msys git 的路径加到 PATH 的最前方……起码是在 Gow 的前面,这样就不会被坑了。

处理完这些乱七八糟的事情之后,运行 boot2docker status 即可看到你的虚拟机的当前状态。下次使用时,只需执行 sh start.sh 即可自动配置好环境变量并且开启 git bash。在这个 git bash 里,你就可以执行你的 docker 指令了~

如果不想用 git bash,那么执行 boot2docker shellinit ,也可以看到应设置的环境变量,如:

export DOCKER_HOST=tcp://192.168.111.222:2376
export DOCKER_CERT_PATH='C:\Users\oott123\.boot2docker\certs\boot2docker-vm'
export DOCKER_TLS_VERIFY=1

此时,用 set 将这些环境变量设置好,即可在 cmd 中使用 docker 来管理 docker 容器了,如:

set DOCKER_HOST=tcp://192.168.111.222:2376
set DOCKER_CERT_PATH=C:\Users\oott123\.boot2docker\certs\boot2docker-vm
set DOCKER_TLS_VERIFY=1

试试 docker info 能不能显示出虚拟机的信息来吧。

Cmder / Listary 搭配使用的若干技巧

Cmder 是一个在 Windows 下用起来很舒服的控制台。以下引自官方网站,请自行阅读。

Cmder is a software package created out of pure frustration over the
absence of nice console emulators on Windows. It is based on amazing
software, and spiced up with the Monokai color scheme and a custom
prompt layout. Looking sexy from the start.

确切的说来,Cmder 是基于 ConEmu 定制的。我这里要说的,主要是 Cmder 如何和其它软件进行集成。

一、 免 UAC 以管理员权限启动 Cmder (或者任何程序)

这里用到的所谓 “免 UAC” 其实是利用 Windows 的计划任务功能。在“控制面板”中搜索“计划任务”打开计划任务的控制台,新建一个任务。路径选择你的 Cmder.exe(新版本)或者 Cmder.bat(老版本),并选上“使用最高权限运行”。触发器可以全都删掉,最后得到的结果大概如下图:

常规标签

然后记住图中的“位置”和“名称”。接着,打开一个非管理员的命令行,执行:

C:\WINDOWS\system32\schtasks.EXE /run /tn "\Best33.com\Cmder"

其中 /tn 后的参数则是“位置”和“名称”用\拼合的结果。

二、在任何地方打开你的 Cmder

这里我的 Cmder 是一个比较老的版本,1.1 吧。新版本很简单,用.\cmder.exe /REGISTER ALL注册就可以了。

老版本的话比较麻烦。我是这么做的:

修改 vendor\init.bat 加入以下内容到最尾部:

@IF "%~1"=="" GOTO endparse
@cd /D %1
:endparse

然后就可以用命令行:ConEmu.exe /Icon <CmderPath>\icons\cmder.ico /Title Cmder /LoadCfgFile <CmderPath>\vendor\conemu-maximus5\ConEmu.xml /Single /cmd cmd.exe /k <CmderPath>\vendor\init.bat "%path%"来启动 Cmder ,其中 %path% 则是你要启动的路径,而<CmderPath>则是你 Cmder 的路径。。

当然,说到 listary ,就不得不提它的智能菜单。我实现了一个这样的功能,双击资源管理器的空白处的菜单中增加了“在这里打开 Cmder 选项”,还是十分的好用的。

双击快速菜单

具体方法,则是在 选项->菜单->智能命令 中,点击“+”->启动应用程序,在“路径”中输入 ConEmu 的路径,大概是<CmderPath>\vendor\conemu-maximus5\ConEmu.exe;“参数”中输入/Icon <CmderPath>\icons\cmder.ico /Title Cmder /LoadCfgFile <CmderPath>\vendor\conemu-maximus5\ConEmu.xml /Single /cmd cmd.exe /k <CmderPath>\vendor\init.bat "%path%"

Listary 设置

附注

由于配置这一系列的东西的时间比较早,现在才整理出来,不免有些杂乱。如果有任何问题可以直接在下面留言。

Win8下的鼠标滚轮穿透软件 AlwaysMouseWheel

新装了Windows8.1,虽然是没有激活但也是能够正常使用的。还好主要生产力工具FireFox和Sublime Text 2都是绿色版,没有多少折腾就进入了正常的状态。

嗯,但是换了系统总是会有些纠结的,比如我就发现我一直使用的MouseInc的鼠标滚轮穿透功能失效了。嗯……也许不是一个普遍现象,因为没有Google到相关的feedback。

于是想着再找另外一个轮子,反正这样的轮子已经造过很多了。找到了一款叫AlwaysMouseWheel的软件。嗯,只有这么一个功能,实测好用。

对了,你可以选择官方下载,或者微云下载