把 WSL 当开发主力机:文件应该放哪,工具应该在哪跑
古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。更完整的更新写在微信公众号「字与码」:工作经历、对新技术的想法,以及这些年走弯路的记录,会不定期发在那里。若觉得博客对你有用,欢迎顺手关注。
我见过不少 WSL 环境,最常见的问题不是装不上 Ubuntu,也不是不会配 VS Code,而是项目放错了地方。
很多人一开始会把代码放在 D:\work\project,然后在 WSL 里进入 /mnt/d/work/project 开发。这个选择很自然:Windows 里能看到,资源管理器能打开,备份软件也熟悉。但项目稍微大一点,git status 变慢,npm install 变慢,测试启动变慢,连编辑器监听文件变化都开始不稳定。
这篇文章只讲一个问题:如果把 WSL 当成日常开发主力机,文件应该放在哪,工具应该在哪跑,什么时候才跨 Windows/Linux 边界。

我会用一个混合项目做例子:后端是 Python,前端是 Node,仓库里有几万小文件,日常会跑 git、uv、npm、pytest、vite。这类项目不算极端,但正好能暴露 WSL 的边界成本。
先说结论:让最忙的工具靠近文件
WSL2 里有两种常见路径。
一种是 Windows 文件系统挂载进来的路径,例如:
/mnt/c/Users/alex/work/api
/mnt/d/work/api
另一种是 Linux 发行版自己的文件系统,例如:
/home/alex/work/api
~/work/api
微软在 WSL 文件系统文档里明确建议:如果你在 Linux 命令行里工作,把项目文件直接放在 WSL 的 Linux 文件系统里,性能会更好。反过来,如果主要用 Windows 工具处理文件,那就放 Windows 文件系统。这个建议听起来朴素,但它是很多 WSL 性能问题的分水岭。
我的实践规则更短:
代码放在最频繁读写它的那一侧。
如果你主要用 git、npm、uv、pytest、make、grep、rg,那它们都在 Linux 里跑,项目就放 ~/work。如果你主要用 Visual Studio、Windows 原生编译器、Windows 版数据库工具,那项目可以放 Windows 分区。不要为了“资源管理器方便看到”把高频 Linux 工作流放到 /mnt/c 下面。
这不是宗教问题,是延迟问题。
一个 Web 项目里有大量小文件:node_modules、.git/objects、测试缓存、构建缓存、类型定义、锁文件。每一次 stat、打开、关闭、写入,都可能跨过 Windows 和 WSL2 的文件系统边界。单次看不出来,几万次叠起来就很明显。
一个最容易复现的慢场景
如果你不确定自己的项目是不是受影响,可以在两个位置各放一份同样的仓库:
mkdir -p ~/bench
cd ~/bench
git clone https://github.com/some-org/some-project.git linux-copy
mkdir -p /mnt/d/bench
cd /mnt/d/bench
git clone https://github.com/some-org/some-project.git windows-copy
不要选太小的仓库。最好是你正在工作的项目,或者至少是一个有几千文件、带依赖安装和测试的项目。
然后分别跑:
cd ~/bench/linux-copy
time git status
time rg "TODO" .
time npm ci
time npm test -- --runInBand
再到 Windows 分区那份:
cd /mnt/d/bench/windows-copy
time git status
time rg "TODO" .
time npm ci
time npm test -- --runInBand
这里不要太纠结单次数字。杀毒软件、磁盘、CPU、省电模式、缓存状态都会影响结果。真正有意义的是同一台机器、同一个项目、同一组命令的相对差距。
我一般会额外跑一个小文件压测,专门看“创建、读取、删除很多小文件”的成本:
cat > /tmp/wsl-file-bench.sh <<'SH'
set -euo pipefail
target="${1:?target dir}"
rm -rf "$target/wsl-bench"
mkdir -p "$target/wsl-bench"
start=$(date +%s%3N)
for i in $(seq 1 8000); do
printf 'hello %s\n' "$i" > "$target/wsl-bench/file-$i.txt"
done
find "$target/wsl-bench" -type f -print0 | xargs -0 cat >/dev/null
rm -rf "$target/wsl-bench"
end=$(date +%s%3N)
echo "$target $((end - start)) ms"
SH
bash /tmp/wsl-file-bench.sh ~/work
bash /tmp/wsl-file-bench.sh /mnt/d/work
这个脚本不代表真实业务,但能很快把边界成本打出来。很多“WSL 慢”的抱怨,本质上不是 Linux 慢,而是把 Linux 工具放在 Windows 文件系统上反复穿墙。
正确迁移项目:不要直接拖目录
如果项目还没有复杂本地状态,最干净的方式是重新 clone:
mkdir -p ~/work
cd ~/work
git clone git@github.com:your-org/your-project.git
cd your-project
然后在 WSL 里重新安装依赖:
uv sync
npm ci
这比从 Windows 目录复制一份 node_modules 过来更可靠。node_modules 里可能有平台相关的二进制包,Python 虚拟环境也有解释器路径,直接搬经常会留下隐性问题。
如果你确实有一些未提交文件,需要从 Windows 目录带过去,我会先在旧目录里确认:
cd /mnt/d/work/your-project
git status --short
能提交就提交。不能提交的,再用 rsync 只同步源码和配置,不同步依赖目录:
rsync -av \
--exclude node_modules \
--exclude .venv \
--exclude .next \
--exclude dist \
--exclude build \
/mnt/d/work/your-project/ \
~/work/your-project/
迁完以后,在新目录跑一轮基础检查:
cd ~/work/your-project
git status --short
uv run pytest
npm test
这一步不要省。迁移环境最怕“看起来能跑”,几天后才发现某个生成目录、软链接或本地配置丢了。
VS Code 应该怎么打开
我平时不从 Windows 版 VS Code 直接打开 \\wsl.localhost\Ubuntu\home\alex\work\project。可以打开,但那样容易把编辑器扩展、文件监听和终端上下文搞得半 Windows 半 Linux。
更稳定的方式是用 Remote - WSL:
cd ~/work/your-project
code .
此时 VS Code 窗口左下角会显示它连接到了 WSL。终端、扩展、语言服务都在 Linux 侧运行。你在编辑器里保存文件,实际写的是 Linux 文件系统;你在终端里跑 pytest,读的也是同一套文件。
如果要从 Windows 资源管理器看这个目录,不要把项目搬回 Windows 分区。直接在 WSL 里执行:
explorer.exe .
它会打开当前 Linux 目录对应的 Windows 资源管理器视图。偶尔拖一个文件、看一张图片、把构建产物发给别人,这样就够了。不要反过来,让 Linux 的高频工具长期跑在 /mnt/d 上。
路径互转:少记,直接问系统
WSL 里有几个工具值得记住。
Linux 路径转 Windows 路径:
wslpath -w ~/work/your-project
输出类似:
\\wsl.localhost\Ubuntu\home\alex\work\your-project
Windows 路径转 Linux 路径:
wslpath -u 'D:\work\your-project'
输出:
/mnt/d/work/your-project
从 WSL 调 Windows 程序:
explorer.exe .
notepad.exe README.md
powershell.exe -NoProfile -Command "Get-ChildItem"
从 Windows 调 WSL 命令:
wsl.exe -d Ubuntu -- bash -lc "cd ~/work/your-project && git status --short"
这些互调能力很好用,但我只把它当“桥”,不把它当“路”。桥是过河用的,不是让你在桥上盖办公室。
.wslconfig 不是性能魔法,但能避免误判
有些人一遇到 WSL 慢,就开始调内存和 CPU。这个方向不是完全没用,但要放在文件位置之后。
全局配置在 Windows 用户目录的 .wslconfig:
[wsl2]
memory=16GB
processors=8
swap=8GB
改完以后:
wsl --shutdown
再重新打开 WSL。
这类配置适合解决“构建时内存不够”“并行编译抢满 CPU”“swap 过大拖慢磁盘”的问题。它不能消除 /mnt/c 上小文件操作的边界成本。也就是说,如果项目位置错了,先搬项目;搬完还慢,再看资源限制。
单个发行版的配置在 /etc/wsl.conf。例如你想控制自动挂载行为、默认用户、systemd、interop:
[boot]
systemd=true
[interop]
enabled=true
appendWindowsPath=false
[automount]
enabled=true
options=metadata,umask=22,fmask=11
我个人会谨慎使用 appendWindowsPath=false。它能减少 PATH 污染,避免误调用 Windows 版 node.exe、python.exe,但也会让一些跨系统小工具不那么顺手。团队里最好写进 onboarding 文档,不要每个人各配一套。
哪些文件还应该留在 Windows
不是所有东西都应该搬进 WSL。
适合留在 Windows 的:
- Office 文档、设计稿、截图、临时下载文件;
- Windows 原生工具主要处理的项目;
- 需要被 Windows 备份软件、同步盘直接托管的资料;
- 游戏、影音、大型非开发素材。
适合放进 WSL 的:
- Linux 工具链主导的源码;
node_modules、.venv、.pytest_cache、.next这类高频读写目录;- Docker bind mount 会频繁访问的服务代码;
- 需要大量
git、rg、find、make操作的仓库。
有一个边界很容易踩:数据库数据目录。
如果 PostgreSQL、MySQL、Redis 运行在 WSL 或 Docker 的 Linux 环境里,数据目录不要放 /mnt/c。数据库对 fsync、锁、权限、大小写、文件改名语义都比较敏感。开发环境图省事还好,真把数据目录挂到 Windows 分区,出问题时很难排查。
一个团队可复制的目录约定
个人机器可以随意一点。团队里建议统一目录,避免文档里到处都是个人路径。
我会推荐:
~/work/company/
product-api/
product-web/
scripts/
~/tmp/
scratch/
downloaded-artifacts/
~/data/
local-postgres/
local-minio/
然后把项目 README 里的命令写成 Linux 路径:
cd ~/work/company/product-api
uv sync
uv run pytest
Windows 侧需要打开目录时,统一使用:
explorer.exe .
如果有人坚持从 Windows 资源管理器进入,也让他访问:
\\wsl.localhost\Ubuntu\home\<user>\work\company\product-api
而不是把项目复制回 D:\work。
迁移后的验证清单
搬完项目后,我通常按这个顺序检查:
pwd
mount | head
git status --short
git config --show-origin core.autocrlf
which node
which python
which uv
which npm
重点看三件事。
第一,pwd 不能在 /mnt/c 或 /mnt/d 下面。
第二,which node、which python 不应该指向 Windows 路径。如果看到 /mnt/c/Program Files/nodejs/node.exe,说明 PATH 混进来了。
第三,换行符设置要稳定。跨 Windows 和 Linux 开发时,core.autocrlf、.gitattributes 最好由项目固定,不要靠个人全局配置碰运气。
一个常见 .gitattributes 可以这么写:
* text=auto eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
这不是 WSL 独有问题,但 WSL 会把它放大:同一个仓库既被 Windows 工具碰,又被 Linux 工具碰,换行符和权限位很容易变成无意义 diff。
我现在的使用边界
我的日常边界大概是这样:
代码、依赖、测试、构建都在 WSL。
浏览器、聊天、Office、图片编辑大多在 Windows。
需要共享文件时,从 WSL 用 explorer.exe . 打开。
需要临时调用 Windows 命令时,用 powershell.exe 或具体 .exe。
需要长期运行的服务,尽量让它在一侧闭环,不要数据在 Windows、进程在 Linux、配置又在第三处。
WSL 最舒服的状态,不是把 Windows 变成 Linux,也不是把 Linux 嵌进 Windows 当玩具。它更像一张开发工作台:Linux 负责工程工具链,Windows 负责桌面和生态,两边通过少数明确的边界连接。
文件放对以后,很多问题会自然消失。git status 不再让人怀疑人生,npm ci 不再像在慢慢拷贝沙子,测试也不会因为文件监听或路径转换冒出一堆怪问题。更重要的是,团队文档可以变简单:进入 WSL,cd ~/work/project,跑命令。不要每次都先解释为什么你的 /mnt/d 比他的 /home 慢。