1. 虚拟机用久了,总有几件事让我忍不住想换
用WSL2替代VMware虚拟机,这个念头最早冒出来,是在一次普通的联调任务里。一个服务要跑在Linux环境,我习惯性打开VMware虚拟机,等它完成那套固定的开机流程。启动桌面、等待自启动脚本全部执行完,然后才敢把窗口最小化。结果那天虚拟机内存占用已经逼近上限,我新搭的测试环境还没来得及建,宿主机的风扇先开始呼呼转。老实说,在只有命令行需求、图形界面几乎不开的前提下,每次为一次联调投入一整套虚拟机的开销,确实越来越觉得不值。
VMware本身并不是不好用,它的完整虚拟化机制是成熟的:独立的硬件模拟、完整的引导流程、可以对网络适配器逐个做精细配置,快照和克隆功能也非常稳。可问题是,我只需要一个能跑命令行工具、做编译、起服务端进程的Linux环境。所谓“杀鸡用牛刀”只是表象,更深层的问题是:牛刀的每一下运作都伴随着肉眼可见的成本。
先说最直观的磁盘占用。一个最小安装的Ubuntu虚拟机,装完基础依赖,虚拟磁盘文件随随便便就几十GB起步,如果中途做过快照,累积占用更是让人看不下去。WSL2使用的虚拟磁盘文件按实际使用量动态扩展,基础镜像往往只有几个GB,而且可以通过命令在空闲状态下压缩回收。对这个差别,只要把两个目录大小对比一下,就能感受到冲击。但磁盘,还不是我换到WSL2的首要理由。
另一个每天都在发生的问题是启动速度和状态切换。VMware虚拟机一旦空闲下来,我总习惯挂起它来释放资源,可挂起、恢复同样要时间,快的话十几秒,慢的话半分钟以上。而且虚拟机内部有自身独立的进程状态,Windows宿主机的文件改动要同步进虚拟机,通常还需要配合共享文件夹或手动拷贝。这套流程用久了,会导致一个很典型的“开发疲劳”:想做点小改动试验,却被环境切换的节奏频繁打断。
所以就我个人而言,核心诉求并不是否定VMware,而是寻找一个替代方案,把“维护一套Linux运行环境”的复杂度降到最低。WSL2吸引我的地方,在于它不再是一个“独立于Windows的平行世界”,而是跟Windows共享内核级协作的子系统。它能在数秒内启动,跟宿主机共享文件系统,还能直接运行Windows下的程序。对于只想要一个顺手Linux环境的场景来说,它击中的恰恰是VMware最钝的软肋。
2. 部署环境时的具体操作:先开功能,再选版本
先说结论:WSL2替换VMware,不是为了追求“某个更轻的模拟器”,而是Windows侧提供的虚拟化机制和Linux子系统直接对接的方案。它背后的结构是轻量级虚拟机加用户态发行版,虚拟化的调度由Windows统一完成,用户侧并不需要安装任何额外的虚拟机管理工具。
2.1 第一步是开启系统功能,而不是急着装发行版
很多人上手WSL,习惯先去搜索“WSL2安装包”,然后在网上找一堆来历不明的脚本。其实最稳妥的做法是从系统自带功能开始。
在控制面板里找到“启用或关闭Windows功能”,勾选“适用于Linux的Windows子系统”和“虚拟机平台”这两个选项。前者提供WSL的运行框架,后者是用来承载WSL2轻量级虚拟机的虚拟化层。这一步必须重启系统才生效,而且光有“适用于Linux的Windows子系统”是不够的,如果只勾它,装出来的可能还是第一代WSL——也就是没有完整内核、通过系统调用翻译层运行的那种。WSL2和WSL1的差异,我会在性能对比里展开,这里先提醒一句:如果你的目标是用WSL2完全替代VMware,一定要确认把“虚拟机平台”一并勾上。
等系统重启完,打开PowerShell或CMD,执行:
wsl --set-default-version 2这条命令的作用是把以后所有安装的发行版都默认为WSL2模式。如果你之前装过旧版本,顺带执行一下:
wsl --set-version <发行版名称> 2它会把已有的发行版从WSL1切换到WSL2。转换过程需要几分钟,期间会重新导入虚拟磁盘,输出信息最后一般会显示“转换完成”。
2.2 发行版的选择:Ubuntu不是唯一答案,但多数情况下够用
有了基础框架,接下来才是选择发行版。我最开始用的是Ubuntu,社区资料多,遇到问题大概率已经有现成解决方案。如果你的需求更偏Kali之类工具链,也可以直接装;但作为替代VMware、日常跑Linux工作负载的场景,我建议还是先选Ubuntu LTS。
一条非常省事的命令是:
wsl --install -d Ubuntu-22.04执行完之后,系统会自动完成下载、部署、初始化,随后弹出一个新窗口,要求你设置Linux用户名和密码。这里有个容易被忽略的地方:WSL2的root账户默认没有密码,安装时候设置的用户是sudo组成员,并不是root。如果你习惯直接以root身份工作,可以在终端里执行sudo passwd root修改,也可以在 /etc/wsl.conf 的[user]段指定启动用户。我的建议是保留默认的非root账户,日常用sudo执行特权操作,这样能避免误删关键文件的概率。
发行版装好后,通过wsl --list --verbose可以查看当前发行版的版本状态和运行状态,第二列为VERSION,应为2。安装多发行版时,可以用wsl -d Ubuntu-22.04指定进入某个发行版,VMware里的多虚拟机管理逻辑在这里被一台系统同时管理多个发行版取代了。
2.3 装完之后需要立刻做的两项设置
第一项是更新软件源和基础包。如果你的网络环境访问默认源较慢,可以把 /etc/apt/sources.list 或 /etc/apt/sources.list.d/ubuntu.sources 里的URL替换成你实际可访问的镜像源。这一步不是必须的,但做完之后apt update && apt upgrade的速度和成功率会明显提升。
第二项是设定 /etc/wsl.conf。WSL2默认在没有配置文件的情况下也能工作,但一旦开发任务变重,有些行为是可以提前锁定的。一个典型的WSL2迁移问题:挂载在 /mnt/c 底下的Windows盘符目录默认元数据为简化模式,文件权限可能不够直观;为了避免奇怪的权限错乱,可以在 /etc/wsl.conf 写上:
[automount] enabled = true options = "metadata,umask=22,uid=1000,gid=1000"这里的 metadata 参数决定了Linux文件属性是否能完整地保存在Windows分区上的NTFS文件系统里,umask=22则让普通文件默认644、目录默认755,基本符合常规工作习惯。改完配置,需要在PowerShell里用wsl --shutdown重启整个WSL,配置才会生效。注意,wsl --shutdown会关闭所有发行版,不只是当前这个,所以别在跑着重要任务的时候执行。
3. 速度、内存、磁盘,三组数据说明为什么它能替代VMware
从一个装了多年虚拟机、也看过不少性能报告的人的角度说,WSL2和VMware的差别,不是“快一点”和“慢一点”的关系,而是使用体验的性质发生了变化。
3.1 启动时间和交互响应
先看启动时间。VMware的完整启动流程要走BIOS自检、引导加载器、内核初始化,再到systemd拉起服务,哪怕不开图形桌面,纯命令行登录也要十几秒到半分钟不等。WSL2的启动机制不一样,它在需要的时候直接由Windows拉起轻量级虚拟机实例,并向内部运行指定的init进程,实测一般能做到两秒左右进入可交互状态,如果发行版被缓存运行,触发时间会更短。这个差别在每次开终端的时候都是能感知到的。
更关键的还不是启动,是“反复切换”的成本。VMware的使用习惯是启动一次虚拟机,长时间把桌面开着,因为你不想等待下一次冷启动。WSL2则把“打开Linux”的粒度缩短到秒级,你完全可以像打开普通终端一样,想用就用,用完就关。这导致一个工作流层面的变化:临时起一个Linux环境做小验证的动作变多了,而不是非要等到“攒一批验证任务再开虚拟机”。
3.2 内存占用:Vmmem进程到底会不会“吃内存”
WSL2的宿主机端会有一个名为Vmmem的进程,代表虚拟机的内存占用。很多人第一次看到它就慌,以为是内存泄漏。我见过的情况是:Vmmem占用的内存会随着WSL里运行的任务升降,但默认设置下,从空闲任务切换回较高的占用值时,系统并不会立刻主动回收全部内容,内存会保持一段时间的“预热”。这不是bug,是虚拟化产品为了减少任务反复升降时的抖动,刻意缓存了热内存。
如果你对内存占用很敏感,可以通过用户目录下的.wslconfig文件限制WSL2能使用的最大内存和处理核数。比如:
[wsl2] memory=4GB processors=4 swap=4GB放在C:\Users<用户名>.wslconfig中,然后执行wsl --shutdown让设置生效。我要补充一个实际使用中得到的结论:WSL2的内存不是固定预留的,它按需分配,但也有一个“回收滞后”的特性;限制到4GB并不会影响多数开发场景,因为多数命令行任务的真实需求远低于这个数字,而且Windows侧还有系统缓存在兜底。
对比VMware:一台配置了4GB内存的虚拟机,启动之后这4GB基本就固定占用了,无论里面有没有跑任务,Hypervisor都要维持完整的客户机内存映射。WSL2的按需分配机制让同样工作负载下的内存峰值通常能控制在VMware的二分之一甚至三分之一,这也是它适合在开发机上长期驻留的原因。
3.3 磁盘占用与镜像体积
关于磁盘,前面提到镜像体积相差很大,这里把数据口径说清楚。VMware的虚拟磁盘常见格式有厚置备和瘦置备,厚置备固定占空间,瘦置备则会随着写入增长,如果中途删除了大文件,虚拟磁盘不一定会自动瘦身。WSL2的虚拟磁盘位于Windows系统盘下的ext4.vhdx文件中,它也是动态增长的,但还有一个好处:VHDX支持在线压缩。当WSL内部释放了大量空间后,可以在PowerShell里执行:
wsl --shutdown Optimize-VHD -Path "C:\Users\<用户名>\AppData\Local\Packages\...\LocalState\ext4.vhdx" -Mode FullOptimize-VHD在装了Hyper-V管理工具的Windows版本上可用,它会压缩VHDX的空白部分。这套流程在VMware里要对应“收缩磁盘”菜单操作,步骤繁琐且必须关机。所以磁盘问题不光是初始体积的差异,还包括后续运维的日常工作量的差异。
| 维度 | VMware | WSL2 |
|---|---|---|
| 启动进入命令行 | 15-30秒 | 约2秒 |
| 空闲内存占用 | 固定预留 | 按需分配,可回收配置 |
| 基础安装后磁盘占用 | 30GB起步 | 通常2-5GB |
| 跨系统文件共享 | 需增强工具或共享文件夹 | 系统级自动挂载与 \wsl$\ 访问 |
| 图形桌面环境 | 完整支持 | 不适用,适合纯命令行场景 |
3.4 WSL1与WSL2的差异,顺便说清选择逻辑
有个容易混淆的点,就是WSL1和WSL2的区别。WSL1的设计是系统调用翻译,它在Windows的文件系统上以特殊进程方式运行,启动更快,跨文件读写更快,但缺少真正的Linux内核,有些依赖内核模块、设备驱动的程序根本跑不起来。WSL2则是真正的轻量级虚拟机,拥有完整Linux内核,系统调用兼容性几乎和原生Linux一致。你要替代VMware,必须用WSL2,否则“替代”就是不完整的。
4. 替代VMware后,三块工作流要重新梳理
环境本身安装好、跑起来只是第一步。对很多从VMware迁过来的人来说,真正的折腾从这一步才刚开始:原来虚拟机里养成的一系列习惯,有相当一部分需要换一种方式来实现。我这里挑三个最容易踩坑的区域,也是我在实际迁移时反复调整过的部分。
4.1 文件共享方式:不再需要共享文件夹
VMware里设置共享文件夹,通常要在客户机里安装增强工具,再挂载一个共享目录,虚拟机和宿主机之间才能方便地互拷文件。这一步本身不难,但容易遇到权限、路径、工具版本等问题。WSL2彻底绕开了这个流程:Windows的所有盘符自动挂载到/mnt/c、/mnt/d这样的路径,Windows侧也能通过\\wsl$\<发行版名>\路径直接访问WSL内部的文件。两头互通,不需要任何额外驱动。
但要注意,跨文件系统的读写性能有差异。在WSL里访问/mnt/c下的Windows文件,性能可能比访问WSL内部文件系统慢一个数量级。所以我的建议是:项目代码放在WSL的Linux文件系统里(例如 ~/project),数据交互通过相对路径完成;只有需要跟Windows侧工具交互的文件,才放到/mnt下。这一点如果你是从VMware转过来,要注意调整习惯——在虚拟机里,共享目录是你主动挂载的;在WSL里,所有Windows盘符自动可见,反而容易让人在性能不敏感的场景里下意识把文件都放在Windows盘上,时间久了,构建速度会很不理想。
4.2 命令行工具的跨端调用
WSL2的一大特性就是可以直接在Linux环境中调用Windows上的可执行程序,比如在WSL的终端里执行notepad.exe打开记事本,或者调用Windows上的PowerShell、git、浏览器。反过来,Windows的命令行里也能直接调用wsl <命令>来在WSL侧执行任务。这种双向互操作,使得很多过去需要在虚拟机里单独装一套Windows工具链的场景被压缩成“只装一次,两边共用”。
实际开发里我比较常用的一个场景是:Windows侧用熟悉的编辑器打开WSL里的文件,保存后立刻在WSL终端里跑构建命令。编辑器本身不需要有“远程连接”能力,因为WSL的文件系统对Windows是直接可访问的,无非就是在\\wsl$\Ubuntu-22.04\home\用户名\project这样的路径上打开文件。比VMware的方案少了一层网络传输和同步,体验要顺滑得多。
4.3 网络与端口访问
虚拟机时代,如果你在客户机里启动了一个服务(比如对某个端口监听),宿主机要访问它,通常需要配置NAT端口转发或桥接网络,还要注意Windows防火墙对虚拟机进程的放行规则。WSL2默认不需要手动配置端口转发:在WSL里启动监听服务后,Windows侧直接用 localhost 或127.0.0.1访问通常是通的,因为WSL2的网络是通过虚拟网卡与宿主机共享一套NAT方案。
这里的坑点在于“通常”。如果你从局域网里的另一台机器直接访问这台电脑上的WSL服务,因为WSL2默认的NAT网络模式,localhost映射通常只在同一台机器上生效,跨设备访问在默认情况下是不可见的。解决办法绕不开两类:一是把服务绑定到WSL的eth0接口并使用wsl hostname -I拿到的IP,但每次重启IP可能变化,所以更稳妥的是在WSL内配置端口转发规则,或者在Windows侧运行一个转发服务,把对外端口转接到WSL内部。这里要提醒的是,WSL2的镜像网络模式在某些较新版本中已经出现,如果条件允许,可以直接在.wslconfig里启用,能把宿主机的网络接口直接镜像给WSL,局域网访问会顺畅很多。
我还遇到过一个跟防火墙相关的操作:当外部设备访问WSL服务时,Windows防火墙可能会拦截来自虚拟交换机网段的数据包。这属于正常的安全策略,不要为了省事直接关闭Windows防火墙,我用的做法是在“高级安全Windows Defender防火墙”里单独放行需要的端口和源IP,在保证安全边界的前提下提供访问能力。
5. 迁过来以后,最让我感到“被替代”的几个实际场景
上面讲的是操作层面的差异。下面我想聊一聊迁移完成一段时间后,工作方式本身发生的变化。有些变化是在一开始换工具时并没有预料到的。
5.1 系统级的systemd服务管理
VMware里的Linux是完整系统,systemd开机自动拉起的服务一应俱全。WSL2默认并不模拟完整的开机流程,早期版本的WSL甚至没有systemd支持,服务要靠手动起进程、写脚本。这大概是替换过程中最容易产生“缺失感”的地方。
好消息是,较新的WSL版本已经支持在 /etc/wsl.conf 中显式开启systemd:
[boot] systemd=true设置后同样执行wsl --shutdown再进入,执行systemctl list-units会看到完整的系统服务。开启systemd之后,像 ssh、cron、docker 这类需要开机常驻的服务,都能按照熟悉的 systemctl enable/start 方式管理。我迁移时第一时间就把 sshd 和容器服务都切到了 systemd 管理下,整个使用习惯跟VMware里的Linux几乎无缝衔接。
5.2 开发工具链的适用度
对很多开发场景来说,WSL2的性能和兼容性已经足够覆盖日常所需。我日常会用到Java、Go、Node.js和Python,编译C++时也能直接用gcc/g++。WSL2里的Linux内核和核心库版本都是跟随发行版走的,跟服务器端的软件环境一致性很高,这一点比VMware的“模拟硬件”更接近生产环境。如果你的工作涉及容器技术,WSL2直接支持在原生环境中运行容器守护进程,或者配合Windows侧的容器桌面工具,工作流会非常顺手。
唯一还不太适合强迁的场景是:需要访问物理设备底层接口的驱动开发、需要大量视频/图形加速的计算任务,以及依赖特定USB扩展设备直连的实验室环境。WSL2的USB直通支持仍在发展中,不如VMware的“连接USB设备”来得直观。我的建议是这类需求保留一台虚拟机以备应急,日常开发负载则大部分交给WSL2。
5.3 容器场景下的资源调度更清晰了
过去我在VMware里搭Linux环境跑容器,实际上是在一个完整虚拟化的客户机里再跑一层容器技术,层叠又多了一层。WSL2则直接提供内核级容器运行条件,容器可以跑在WSL2的内部,两者之间少了一层虚拟化损耗。对I/O密集型的构建任务,这个差异是可以感知的:同一套镜像构建流程,在WSL2里跑,通常比在VMware的虚拟机里跑快不少。
另一个体会是,WSL2对Windows进程和Linux进程间的互操作支持,让我可以在同一个终端里同时管理宿主机和容器侧的任务,而不需要像从前一样在两个窗口之间切换来切换去。这种沉浸式的工作流体验,是替代方案里最有说服力的一部分。
5.4 应对“重启后忘记启动虚拟机”的事故
最后说一个很琐碎但高频的痛点。VMware时代,重启电脑之后如果忘了启动虚拟机,开发相关的所有操作会瞬间卡住:命令行找不到Linux环境,服务没起来,脚本跑不了。WSL2的思路不同,它按需启动:你开着终端第一次进入WSL,它自动拉起;不进入,它就安静地待着。这个设计让“重启电脑”几乎不再破坏我的工作上下文。需要长期运行的服务,配置systemd,再配合Windows登录时的一条启动命令即可,所有后台服务恢复同样很快。
6. 迁移过程里踩过的坑,以及补救方法
这一节的内容,是我从VMware正式切换到WSL2之后,实际碰到的一些不算骇人听闻但足够烦人的问题,它们足以让你在刚迁移的那几天里怀疑自己的选择。
6.1 多次切换版本后,WSL2状态没有生效
如果你之前在WSL1模式下用过,后来才通过wsl --set-version切换,切换完成后偶尔会出现“明明显示版本为2,但某些行为还是WSL1”的情况。这是因为切换本身是异步完成的,系统提示“转换完成”之后,可能仍有部分缓存未刷新。解决办法非常简单:执行wsl --shutdown,等几秒再重新进入,一般就正常了。如果切换过程报“‘结束错误’”,多半是发行版的安装目录被移动过,先wsl --unregister再重新安装发行版,虽然步骤麻烦,但比排查半天靠谱得多。
6.2 Vmmem进程内存居高不下的处理
前面提到Vmmem会保持一定量的缓存。如果你观察到Vmmem持续占用在数GB甚至满格,优先检查的是:WSL里是不是有进程在后台占着内存。可以用free -h看WSL内部的内存使用,用ps aux --sort=-%mem看哪个进程吃得多。另一种常见原因是WSL里跑的进程在等待时仍然持有mmap的内存,比如Java或Python的解释器。如果确认内部进程没问题,再考虑在 .wslconfig 里限制最大内存,同时缩短交换分区的大小,让系统更快回落。
我看到有些文章建议直接禁止WSL的自动回收,其实没必要。把Windows默认的内存压缩机制关掉,反而会影响Windows自身的运行效率。我采取的方案是:在 .wslconfig 里设置[wsl2] memory=6GB swap=2GB,同时对日常工作负载做了个约定——长时间不用的Linux任务,就wsl --terminate <发行版>手动结束实例,下次用时再自动启动,既灵活又可控。
6.3 文件权限显示为777的疑惑
WSL2里,在/mnt/c下创建的目录经常会出现权限显示为777或755之类的情况,而Linux文件系统里创建的文件则有着正常的权限。很多人以为系统故障了,其实不是,这是NTFS文件系统本身的权限模型与Linux不兼容导致的。WSL访问NTFS时,默认使用Windows对每个文件分配的访问控制列表来映射成Unix权限;在没有元数据情况下,目录可能默认就是777,文件可能默认就是755/644。前面在wsl.conf里设置的 metadata 选项,就是为解决这个问题存在的。挂载时加了metadata之后,你可以用chmod调整权限,并把权限信息存储在NTFS的扩展属性里。如果你想某个挂载目录的权限总是反射到Windows侧,可以设置[automount] options="metadata,umask=22,uid=1000,gid=1000"。
6.4 网络转发与防火墙特性的临时调整
开发时常需要从WSL内部拉取软件包,如果你的网络环境有专用的转发服务,WSL2内访问可能需要单独配置相关环境变量。这里的处理可以沿用Linux下的标准做法:在 /etc/profile 或 /etc/environment 中导出 http_proxy 和 https_proxy 变量。需要说明的是,如果你在Windows侧开着转发代理,WSL2不一定自动继承,大概率要手动设置。很多教程会建议关掉Windows防火墙以求省事,我不建议那么做,因为那会把整个系统的安全边界暴露出去。正确的做法是只为WSL虚拟网卡所在的专用网络开启相应转发或放行规则。
6.5 如果镜像文件增长太快的处理
WSL2里如果频繁安装大型依赖包、跑容器、装卸中间版本软件,ext4.vhdx 文件会膨胀得比较快。这种情况除了日常注意清理 apt 缓存、容器悬空镜像之外,核心处理手段还是回到压缩 vhdx:关掉WSL,执行收缩命令,再把WSL拉起来。周期性的压缩能避免磁盘占用失控。相比VMware的虚拟磁盘处理,这套流程虽然也需要几步命令,但整体可控性和重复执行成本低得多。在自动化程度高的机器上,这条压缩流程甚至可以直接写成一个计划任务,每月执行一次,彻底避免虚拟磁盘体积缓慢侵蚀宿主磁盘的问题。
迁移后的最后几句话
回到最初的问题:用WSL2替代VMware,值不值得?我的回答是,对于多数需要Linux环境的人来说,答案已经从“可以考虑”变成“值得一试”。它并非完美,比如跨文件系统的I/O性能和网络模式的限制依然是真实的痛点,但它在启动速度、资源占用、开发工作流集成等方面,提供了VMware所无法提供的轻量感。
我自己过了适应期之后,最大的体会是,工具本身好坏往往不是决定性因素,关键是它是否匹配你的使用习惯。WSL2的上手曲线在前一两天会有一点“别扭”,毕竟它的交互模型和传统虚拟机不完全一样,但你只要坚持用三天,大概率能感受到那种“开个Linux环境就像开个普通终端”的舒适感。如果你也在VMware和WSL2之间纠结,建议先在新环境上装一个发行版,把日常工作负载跑上几天,再对要不要彻底切换下判断。