☰
WSL2实战指南:在Windows上无缝运行Linux程序的完整方案
2026/10/8 19:53:04 网站建设 项目流程

先交代一个几乎每个后端开发者都会遇到的场景:你在 Windows 上写代码,线上服务器是 Linux,本地跑着好好的功能一到服务器就出了怪问题。来回切虚拟机、双系统、远程连服务器调试,每一步都在浪费时间。WSL(Windows Subsystem for Linux,Windows 子系统)就是解决这个矛盾的直接答案,它让你不用离开 Windows,就能原生运行 Linux 程序、编译 Linux 工具链、复现服务器环境。这篇内容我会从方案取舍讲起,用完整的示例代码带你在 WSL 里跑通编译、脚本、服务部署,再把我在实际使用中踩过的坑一并整理出来。无论你是刚接触 Linux 的新手,还是常年混迹终端的老人,这套流程都能直接照搬。

1. 为什么要在 Windows 上运行 Linux 程序:方案的取舍与思路

1.1 三种常见方案的对比

在 WSL 出现之前,我试过虚拟机,也折腾过双系统,体验都不算好。虚拟机的好处是隔离干净,坏处是资源开销大。开一个 Ubuntu 虚拟机,内存吃掉 2-4GB,磁盘占用几十 GB,每次启动都要等一两分钟,文件在 Windows 和虚拟机之间来回拖动也很别扭。双系统则是另一个极端——机器性能跑得满,但你一次只能用一套系统,想同时看 Windows 里的资料和 Linux 里的代码,只能重启切换,来回折腾几次耐心就没了。

WSL 的方案正好站在两者中间。它不像虚拟机那样需要完整模拟硬件,而是把 Linux 系统调用直接映射到 Windows 内核上(WSL 1 的做法),或者在轻量级虚拟化层里跑一个完整的 Linux 内核(WSL 2 的做法)。从用户视角看,你打开终端输入wsl,就进入了一个真正的 Linux 环境,能执行apt、gcc、python3,能访问localhost端口,而且 Windows 和 Linux 之间的文件互通非常流畅。

这里要先搞清楚一个概念:WSL 和"在 Windows 里装个 Linux 虚拟机"不是一回事。虚拟机里的 Linux 是一个独立的完整系统,有自己的引导、内核、初始化流程;而 WSL 是被 Windows 调度和管理的子系统(WSL 2 虽然底层用了轻量级虚拟机,但交互方式完全不是虚拟机的操作体验)。这个区别直接决定了你后续对网络、端口、文件系统的处理方式。

1.2 WSL 1 和 WSL 2,怎么选

WSL 1 是把 Linux 系统调用翻译成 Windows 系统调用,所以它的文件系统性能和 Windows 原生文件一致,启动快、内存占用小。但缺点也很明显,某些直接操作内核、依赖内核模块的程序跑不了,比如 Docker 容器,或者需要iptables、cgroup的工具,在 WSL 1 下就是不行。这也是早期很多人用完 WSL 后觉得"这个也不行、那个也缺"的主要原因。

WSL 2 改成了真正的轻量级虚拟机里跑完整 Linux 内核,系统调用没有翻译损耗,Docker、systemd、内核模块这些都能用了。代价是它占用内存和磁盘更多,而且跨文件系统访问(比如 WSL 里访问C:\work下的项目)会比纯 Linux 内部操作慢不少——因为要经过 9P 协议做文件系统桥接。

我的建议很直接:新上手就别纠结,用 WSL 2。微软官方也已经默认推广 WSL 2,新版本安装完默认就是 2。如果你的机器配置很旧、内存只有 4GB,平时只是跑点脚本,那 WSL 1 的轻量优势还是有价值的。但但凡你打算用 Docker、跑服务、做正经开发,WSL 2 是唯一合理的选择。

1.3 适用场景和它的边界

先说清楚 WSL 能做什么,免得你装了之后有落差。日常开发场景里,它覆盖了绝大部分需求:命令行工具、编译器(gcc、clang)、脚本语言(Python、Node.js、Ruby)、包管理(apt、pip、npm)、nginx 和数据库服务、Git 操作、Ansible 脚本,还有 VSCode、JetBrains 全家桶的远程开发模式。这些在 WSL 里的表现和一台独立的 Linux 服务器几乎一致,这也是它能成为"本地模拟生产环境"第一选择的原因。

要分清边界的是:WSL 不适合跑图形界面为主的重型应用。虽然 WSLg 已经能支持 GUI,直接运行一些 Linux 图形程序也没问题,但如果你需要的是完整的 Linux 桌面环境,或者依赖特殊硬件驱动的应用(比如某些 GPU 直通场景),WSL 就不是这套方案的主场。另外,WSL 运行的是用户态程序,内核是你自己装的发行版的内核,所以任何需要加载自定义内核模块的场景,WSL 2 的支持也非常有限。想明白这些边界,你对它能不能用在某个具体场景的判断会更快。

2. 环境准备:WSL 的完整安装与基础配置

2.1 先确认系统版本,再执行一键安装

WSL 的安装前提很简单:Windows 10 版本号在 2004 及以上,或者 Windows 11。我自己用的 Windows 11 一路顺畅,不过 Windows 10 更早版本也有 WSL,只是需要手动开启功能。

安装的第一步,打开 PowerShell(管理员模式),直接执行:

wsl --install

这条命令会自动帮你完成三件事:启用两个 Windows 功能("适用于 Linux 的 Windows 子系统"和"虚拟机平台")、下载安装 WSL 内核、安装默认的 Ubuntu 发行版。执行完按提示重启系统,然后就开始 Ubuntu 的初始化配置。

如果你不想用默认的 Ubuntu,可以在安装前先看有哪些发行版:

wsl --list --online

输出类似:

以下是可用的有效发行版列表。 NAME FRIENDLY NAME Ubuntu Ubuntu Debian Debian GNU/Linux kalilinux Kali Linux Rolling Ubuntu-22.04 Ubuntu 22.04 LTS Ubuntu-24.04 Ubuntu 24.04 LTS

注意wsl --install装的是默认版本,想用别的发行版,可以在重启前先卸载默认的,也可以安装之后再添加。我的实际经验是:先让它默认装一个 Ubuntu,跑通流程,以后想加 Debian 或 Kali 随时可以wsl --install -d Debian再装一个。多发行版可以共存,用wsl -d Debian指定进入。

2.2 WSL 2 要求手动开启的功能项

如果你的 Windows 版本稍旧,或者之前没有启用过虚拟化,wsl --install可能会卡在某个环节。这时候手动启用两个 Windows 功能比较可靠:

在 PowerShell 管理员模式下依次执行:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

第一条开启 WSL 功能,第二条开启虚拟机平台。执行完重启电脑,再单独更新 WSL 内核。老版本 Windows 10 需要从微软官网下载 WSL 2 内核更新包安装,新版本会自动处理。

有个参数值得说一下:/norestart的意思是当前先不重启,两条命令都执行完再统一重启,省得重启两次。如果你的机器 BIOS 里没有开启 CPU 虚拟化(VT-x/AMD-V),虚拟机平台功能会起不来,需要进 BIOS 打开——这是少数 WSL 2 强制依赖的硬件条件,Intel 和 AMD 都有对应的设置选项,默认基本都是开启的,但个别品牌机出厂会关掉。

2.3 把系统装到 C 盘之外

WSL 默认发行版都是装到C:\Users\你的用户名\AppData\Local\Packages目录下的,几年用下来会膨胀到几十 GB。系统盘不够大的话很容易爆掉。我的解决思路是:装好系统之后立刻迁移。

在 Windows 下执行导出:

wsl --export Ubuntu D:\wsl\Ubuntu.tar

然后注销默认系统:

wsl --unregister Ubuntu

再导入到 D 盘:

wsl --import Ubuntu D:\wsl\Ubuntu D:\wsl\Ubuntu.tar

其中D:\wsl\Ubuntu是目标目录,导入后所有 WSL 数据都会存放在这里。注意:用--import导入的系统默认使用 root 用户,如果你想和第一次初始化那样使用普通用户,还需要在 WSL 里手动设置一个默认用户。这一步的具体操作,我在后面第 4 章里会展开说明。

导出文件是一个 tar 包,几十 GB 的系统导出后可能 10-20GB,压缩和恢复过程比较耗时,我建议拿到新机器第一次装好的时候就迁移,别等系统用了很久再折腾。另外记得定期清理,磁盘空间是 WSL 使用中最容易被忽略的问题。

2.4 用 .wslconfig 配置文件控制资源占用

WSL 2 默认会使用机器内存的一半作为虚拟机内存上限,机器只有 16GB 内存的话,WSL 能吃掉 8GB。这本来是合理的资源分配,但如果你只是偶尔开 WSL 跑几个命令,这个默认策略就有点浪费了。

在C:\Users\你的用户名\.wslconfig下可以配置资源限制:

[wsl2] memory=4GB processors=4 swap=8GB localhostForwarding=true

memory控制 WSL 2 最大可用内存,processors控制虚拟 CPU 数量,swap是交换分区大小,localhostForwarding保持默认的 true 就好——它决定了你从 Windows 访问 WSL 里启动的服务时能不能直接用localhost。配置完成之后需要重启 WSL 才会生效:

wsl --shutdown

再输入wsl重新进入。这个配置文件改动频率不高,但关键时候能救你机器一命,尤其是开发机还跑着 Docker、虚拟化软件的时候。

3. 核心实操:从零开始跑通 Linux 程序

3.1 直接进入系统,第一个命令

安装完成后,终端输入:

wsl

屏幕上会出现 Linux 风格的提示符,类似:

Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-31-generic x86_64) 你的用户名@你的主机名:~$

先用一组命令做基础配置:

sudo apt update sudo apt upgrade -y

sudo apt update是刷新软件源列表,upgrade是把已有的包升到最新。刚装好的系统这一步必须做,不然后面安装软件包容易碰到依赖版本过旧的问题。实际执行时,apt upgrade可能需要一两分钟,网络慢的话耐心等。

确认系统正常后,你可以试试在 WSL 里执行几个 Linux 命令:

uname -a cat /etc/os-release

uname -a会显示内核版本——WSL 2 能看到一个microsoft后缀的内核,这是正常的;cat /etc/os-release显示发行版信息。这两个命令是以后排查环境问题时最常使用的"开场白"。

3.2 示例一:编译一段 C 程序

适用场景很明确:你想确认 WSL 的编译工具链是否可用,或者想跑一个只能在 Linux 下编译的 C/C++ 项目。下面这段代码我给不少同事演示过,几十秒就能确认环境通了。

先安装编译器:

sudo apt install -y gcc make

然后创建源文件hello.c:

#include <stdio.h> int main(void) { printf("Hello from WSL!\n"); return 0; }

用vim或nano创建文件(我个人习惯用nano,操作门槛低):

nano hello.c

写入上面的代码后按Ctrl+O保存,Ctrl+X退出。然后编译运行:

gcc hello.c -o hello ./hello

输出:

Hello from WSL!

这整个过程和在原生 Linux 上没有任何区别。关键点是:这个程序直接运行在 Linux 内核上,不是 Windows 的 exe 程序。你可以试试file hello,会看到它是一个 ELF 格式的可执行文件(Linux 的标准可执行格式),不是 PE 格式。这就是"Windows 上运行 Linux 程序"最直白的诠释。

3.3 示例二:用 Python 跑一个数据处理脚本

很多做后端、数据处理的同学在 Windows 上搭 Python 环境容易遇到路径分隔符、编码、依赖包编译失败等问题。WSL 里就是原生 Linux 环境,大部分问题直接消失。

Ubuntu 24.04 自带 Python 3.12,但默认没有 pip,先安装:

sudo apt install -y python3-pip python3-venv

注意,Ubuntu 24.04 对 Python 包采用了一个新策略:系统自带的 Python 环境被标记为"外部管理"(externally-managed-environment),直接pip install会提示错误,要求你先建虚拟环境。要习惯这个做法:做 Python 开发,永远先建虚拟环境。

mkdir -p ~/demos && cd ~/demos python3 -m venv myenv source myenv/bin/activate pip install pandas

等到pandas装好,你可以开始写一个命令行下运行的脚本。比如analysis.py:

import pandas as pd data = {'name': ['Tom', 'Jerry', 'Spike'], 'score': [87, 92, 78]} df = pd.DataFrame(data) print(df.describe())

运行:

python3 analysis.py

pandas这种重量级数据包在 Windows 下安装,偶尔会遇到二进制包不匹配的麻烦,WSL 里基本是装完就能用。这也是为什么我现在本地 Python 开发都放在 WSL 里——顺手解决了 Windows 上 Python 环境一堆历史遗留问题。

3.4 示例三:10 秒启动一个 nginx 服务并访问

跑一个 Web 服务能更直观地看到"从 Windows 访问 WSL 里的 Linux 程序"这件事。用 nginx 做演示最合适,安装简单、访问立即见效。

sudo apt install -y nginx sudo service nginx start

然后打开 Windows 浏览器,访问http://localhost。正常情况下你会看到 nginx 的默认欢迎页。

原理上,WSL 2 会做 localhost 的端口重定向,WSL 里的程序监听某个端口时,Windows 的localhost能直接映射过去。这步还原了"本地开发预览线上服务"的体验。

如果你不想手动启动服务,也可以配置 WSL 开机自动启动某个服务。新版 WSL 支持 systemd,在/etc/wsl.conf里加一段:

[boot] systemd=true

然后重启 WSL(先wsl --shutdown再进入),执行:

sudo systemctl enable nginx

以后每次进入 WSL,nginx 就会自动运行,Windows 浏览器随时都能访问到。我在本机调试前端页面时就是这么用的,省掉了每次手动service nginx start的步骤。

3.5 用 VSCode 把编辑器接进来

命令行操作验证完,就该谈实际开发体验了。VSCode 配合 WSL 的体验基本等同于在 Linux 原生环境开发,这也是 WSL 被广泛接受的重要原因。

在 Windows 版本 VSCode 里安装官方扩展"WSL"(扩展名是ms-vscode-remote.remote-wsl),然后打开 VSCode,按Ctrl+Shift+P,输入"WSL: Connect to WSL",选择打开文件夹。

也可以用命令行方式——在 WSL 里定位到项目目录:

cd ~/demos code .

VSCode 会自动启动并以"WSL: Ubuntu"模式打开,此时 VSCode 的终端、调试器、语言服务全部运行在 WSL 内部。你能直接调用的 Linux 命令、编译器、Python 解释器,都在 Linux 文件系统上工作,不再有 Windows 交叉访问的兼容性问题。

这种"Windows 编辑、Linux 运行"的模式,其实比单纯用虚拟机更贴近日常开发流程:编辑器在 Windows 上有更好的界面和插件生态,程序运行在 Linux 上拿到一致的行为表现,两边各自发挥长处。

3.6 目录位置和路径那几个坑

使用 WSL 时,/mnt/c是 Windows 的 C 盘,/mnt/d是 D 盘。你可以在 WSL 里通过路径cd /mnt/c/Users/你的用户名/Desktop进入 Windows 桌面。

但我要强调一个从实践中得出的重要习惯:项目文件尽量放在 WSL 自己的 Linux 文件系统里(比如~/project),不要放在/mnt/c下面。原因在于 WSL 访问 Windows 盘是通过 9P 协议桥接的,频繁读写、编译时尤其慢。同一个项目,放在 Linux 文件系统里编译只要几秒,放在/mnt/c下可能就要十几秒甚至更久。文件读写多的开发任务(Git 操作、npm install、编译)除非必要,否则都放到 Linux 侧。

4. 常见问题与排查技巧实录

4.1 安装时没有让你创建用户名密码?

新版本 WSL 初始化时通常会让你先输入用户名和密码,创建 Linux 侧的管理账号。但如果你之前通过wsl --import方式恢复过系统,或者初始化环节被跳过了,系统默认只有 root 用户。

这种情况解决办法是重新设置默认用户。在 WSL 里以 root 身份执行:

useradd -m -s /bin/bash 你的用户名 passwd 你的用户名 usermod -aG sudo 你的用户名

然后在 Windows 侧写一份/etc/wsl.conf:

[user] default=你的用户名

存好后执行wsl --shutdown再进入,默认用户就切到普通用户了。总的原则是:日常操作尽量不用 root,避免权限混乱,只在需要安装系统级软件时用sudo。

4.2 localhost 能通但通过 IP 访问不了?

WSL 2 的网络地址和 Windows 并不完全相同。Windows 浏览器访问http://localhost能通,是因为 localhostForwarding 的默认机制;但如果你访问 WSL 的真实 IP(在 WSL 里用ip addr查到的eth0地址),Windows 侧不一定能直接通。反过来,WSL 里如果想访问 Windows 上启动的服务,用的通常是localhost或者 Windows 主机的局域网 IP。

如果你有一个开发场景是"其他设备(比如手机、另一台电脑)要通过 Windows 的 IP 访问 WSL 里的服务",那需要额外的端口转发。在 Windows PowerShell 里做端口转发:

netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=127.0.0.1

这会把 Windows 的 8080 端口转发到 WSL 的 localhost 8080。注意 WSL 的 IP 可能会变化,所以真实生产场景里用localhost做转发目标最省心。这类网络问题排查起来挺抽象,但实际遇到不多,记住"WSL 的 IP 不是固定 IP"就够应对大部分困惑了。

4.3 磁盘空间越占越多,怎么回收

WSL 的磁盘占用会只增不减,因为它的虚拟磁盘文件(ext4.vhdx)在删除内部文件后不一定自动缩小。如果你删过不少东西但系统盘空间没回升,大概率就是这个问题。

回收思路是压缩虚拟磁盘。先彻底关闭 WSL:

wsl --shutdown

然后找到发行版磁盘文件的路径,一般在%LOCALAPPDATA%\Packages\下以发行版命名的目录里,文件是ext4.vhdx。用管理员 PowerShell 执行:

diskpart select vdisk file="C:\Users\你的用户名\AppData\Local\Packages\...\ext4.vhdx" attach vdisk readonly compact vdisk detach vdisk exit

compact命令会把虚拟磁盘未使用部分的空间压缩出来。实操中能回收几十 GB 的情况也有。如果你把 WSL 迁移到了 D 盘,路径就按实际存放位置找。这个方法适合定期执行,尤其在你频繁安装卸载开发依赖之后。

4.4 装了内核驱动或 Docker 后,WSL 突然失灵

Docker Desktop 的 WSL 集成,是新用户比较容易卡住的环节。Docker Desktop 安装完成后,通常在 Settings 里选择 "Use the WSL 2 based engine",然后在 "Resources -> WSL Integration" 里启用对应的发行版后,你在 WSL 里才能直接用docker命令。

如果你在 WSL 里手动执行docker提示命令找不到,多半是 Docker Desktop 没有集成到当前发行版。检查两处:Docker Desktop 是否正在运行;WSL Integration 是否勾选了你正在用的发行版。还有一种阴间情况:Docker Desktop 正常,WSL 里docker version也有输出,但拉镜像特别慢或者报网络错误,这是 Docker Hub 网络波动问题,换个镜像源就能缓解。

4.5 WSL 整体变慢,怎么定位瓶颈

WSL 2 变慢的原因通常有三个:内存不足导致 swap 频繁、跨文件系统读写太重、Windows 侧杀毒软件过量扫描 Linux 文件。

先用free -h看看内存和 swap。如果 swap 占用很高,说明内存紧张,在.wslconfig里把memory调大一些。然后看项目文件位置:在~目录下还是/mnt/c下,如果后者,把项目复制到 Linux 侧,重试之前的编译或运行耗时,会有肉眼可见的差别。

杀毒软件这块,Windows Defender 默认会实时扫描 WSL 文件,对依赖大量文件读写的项目影响明显。可以给 WSL 的工作目录添加 Defender 排除项,路径填 Windows 侧的目录(比如D:\wsl\)。这一步对大型项目收益很高,编译和 npm install 都能快不少。

5. 一点真心话

WSL 用了这些年,最大的体会是它解决了一个很尴尬的问题:开发环境离生产环境太远。以前我在 Windows 上写代码,调试完要部署到 Linux,总得经历一轮"环境差异战"。现在 WSL 里跑的就是 Linux 生态,脚本、依赖、服务行为都和服务器对齐了,写完直接部署的自信高了很多。

最后再分享一个小技巧:给 WSL 设置 Windows Terminal 作为默认终端,再把 VSCode 集成好。这套组合拳打下来,日常开发很少需要专门打开"虚拟机"这个界面去等启动、做快照了。要是你还在用虚拟机对比 WSL,建议真正动手跑一周,大概率就回不去了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询