开发时选 WSL 还是 VPS?可用性与性能对比
WSL 与 VPS 并非替代关系:了解关机后的运行状态、systemd 0.67.6 支持、文件性能、公网 IP、备份责任,以及连接两者的 SSH 方案。
开发时应使用 WSL 还是 VPS?
开发时选择 WSL 还是 VPS,关键取决于一个属性:可用性。WSL(Windows Subsystem for Linux)会在虚拟机中运行 Ubuntu,该虚拟机的生命周期与 Windows 会话相同。VPS(virtual private server)会在公网 IP 地址上运行同一个 Ubuntu;即使您合上笔记本电脑,该地址仍保持可用。大多数开发者最终会同时使用两者,并将服务器作为持续可访问的机器。
操作系统并不是关键区别,因为两者运行的都是 Ubuntu。真正不同的是运行时间、从互联网访问的能力、systemd 能提供的保证、文件处理速度、网络行为,以及由谁负责备份。下面的每个部分都介绍一种差异,您可以在自己的机器上实际观察到这些差异。
关闭笔记本电脑后,WSL 为什么会停止?
WSL 2 在轻量级虚拟机中运行真实的 Linux 内核,Windows 会按需启动该虚拟机。只有在某个发行版运行时,该虚拟机才会存在;只有在有程序使用某个发行版时,该发行版才会运行。请从 PowerShell 查看状态:
wsl --version
wsl --list --running关闭所有 WSL 终端,等待一分钟,然后再次运行 wsl --list --running。当它报告没有正在运行的发行版时,您启动的 shell 及其运行的所有内容也都已退出。wsl --shutdown 会立即执行相同操作,可用于测试系统重启后的行为。
睡眠和休眠也会停止该虚拟机。设置为在 03:00 转储数据库的计时器,在笔记本电脑合上盖子时不会触发,因为负责执行它的内核并未运行。系统不会记录错误,因此看起来就像该任务从未被调度过一样。正是这一行为促使人们使用第二台机器:构建队列、聊天机器人、夜间备份或 webhook 接收器都需要一台持续运行的计算机。
systemd 是否在 WSL 中工作?
可以。WSL 0.67.6 开始提供支持,但旧版安装默认未启用。未启用时,systemctl status ssh 会输出:
System has not been booted with systemd as init system (PID 1). Can't operate.先读取配置文件,因为其中可能已经存在相关配置。如果没有 [boot] 部分,就追加一个;如果已有该部分,就在现有部分中添加这一行。
cat /etc/wsl.conf
sudo tee -a /etc/wsl.conf >/dev/null <<'EOF'
[boot]
systemd=true
EOF在 PowerShell 中运行 wsl --shutdown,打开一个新的 Ubuntu shell,然后使用 systemctl list-units --type=service --state=running 检查。列出 unit 表示 systemd 是 PID 1,此后 journalctl -b 即可正常工作。
关键在于 enable 在不同计算机上具体保证什么。在 VPS 上,sudo systemctl enable --now caddy 表示服务会在启动时启动,因此即使没有用户登录,重启或内核升级后服务也会恢复运行。在 WSL 中,它表示服务会在发行版启动时启动,而发行版会在您打开终端时启动。因此,服务只会在您工作期间运行,这与服务存在的目的相反。容器也存在同样的问题,所以让 Docker Compose 服务在启动时启动取决于 WSL 是否执行启动,而 WSL 只有在您要求时才会启动发行版。
Webhook 能访问运行在 WSL 中的服务器吗?
没有额外配置时不能,原因在于网络布局。WSL 2 默认将虚拟机置于独立虚拟适配器后的 NAT(网络地址转换)网络中。查看该地址:
ip -4 addr show eth0
ip route show default该地址是私有地址,并且每次虚拟机启动时都会重新分配,因此会发生变化。Windows 本身仍可访问 localhost:3000,因为 WSL 会将 localhost 连接转发到该发行版。网络中的其他计算机无法访问,除非通过 Administrator PowerShell 添加代理规则:
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=172.24.108.3该规则指定了一个地址,因此下次地址变化时就会失效。更好的选择是使用镜像网络:该发行版会获得与 Windows 相同的网络接口和地址。截至 2026 年 8 月,该功能需要 Windows 11 22H2 或更高版本。将以下内容写入 %UserProfile%\.wslconfig,然后运行 wsl --shutdown:
[wsl2]
networkingMode=mirrored镜像模式可以解决本地网络访问问题,但不会为你提供公网地址。你的路由器还会执行一次 NAT,大多数家庭网络连接都没有可由你控制的入站端口,许多 ISP 还会在上层再增加一层 NAT。因此,GitHub 无法向你的笔记本电脑 POST 事件,同事也无法打开你的演示链接。隧道服务可以绕过这些限制,但隧道客户端运行在笔记本电脑上,这意味着笔记本电脑仍必须保持唤醒。
VPS 从问题的另一端解决这一限制。它拥有公网 IPv4 地址,通常也拥有公网 IPv6 地址,并且只有你开放的端口可访问。将 A 记录指向它,允许 80 和 443 端口的流量,它就能从任何位置响应。这也是申请公开证书的前提,因为 HTTP-01 challenge 要求 Let's Encrypt 通过公网名称的 80 端口获取文件。在服务器上,通过 使用 Certbot 和 nginx 获取 Let's Encrypt 证书 只需 5 分钟,而在 WSL 中无法完成。对于本地工作,你仍可通过 将自有 CA 添加到 Ubuntu 信任存储,在 WSL 中使用浏览器信任的 HTTPS。
为什么在 /mnt/c 上运行 git 很慢?
因为这些文件不在 Linux 文件系统中。WSL 提供了两个成本差异很大的存储区域。您的主目录位于虚拟磁盘中的 ext4 文件系统上,行为与普通 Linux 磁盘相同。/mnt/c 是 Windows 驱动器,由 Windows 端的组件通过 9P 协议(Plan 9 文件系统协议)提供,因此每次 open 和 stat 都必须跨越这一边界。
处理一个文件没有问题。在大型仓库中,git status 会执行数千次 stat 调用,每次调用都要承担跨越边界的开销。请实际测量,不要盲目相信任何人提供的数值,包括本页面中的数值:
cd /mnt/c/Users/you/code/myrepo && time git status
cp -r /mnt/c/Users/you/code/myrepo ~/myrepo
cd ~/myrepo && time git status每条命令运行两次,并比较第二次运行的结果,以确保两次运行都使用热缓存。Windows 实时防病毒扫描还会增加 /mnt/c 端的开销。因此,同一个仓库在公司笔记本电脑上的运行体验可能比在个人电脑上更慢。
在 WSL 中,解决方法是将工作副本放在 ~ 下,并使用编辑器的 WSL 远程模式打开它。该模式会在发行版内部运行编辑器服务器,而不是跨越边界访问文件。您仍然可以在 Explorer 中通过 \\wsl.localhost\Ubuntu\home\you 浏览这些文件。VPS 不存在此问题,因为它只有一个 Linux 文件系统。VPS 的代价是编辑时的网络延迟,因此用户通常会在终端复用器中工作,或使用远程编辑器会话。在小型服务器上,共享 CPU 资源是需要注意的问题;如果邻居负载过高,嘈杂邻居占用的 CPU 时间 会在 top 中显示为 st 列。
WSL 明显更占优势的方面
- 免费,并且已经在本机上。启用它、安装 Ubuntu 后,1 分钟内即可开始工作,无需付费,也没有需要防护的公网暴露面。
- 它可以随时丢弃,而服务器不能这样处理。
wsl --export Ubuntu D:\wsl-backups\ubuntu.tar将整个发行版写入一个文件,wsl --import可从该文件恢复发行版,或使用第二个名称克隆它。在这里尝试新的 Ubuntu 版本,只需执行克隆和回滚;而将 VPS 从 24.04 升级到 26.04是一次单向变更,还必须避开当前已运行服务的时间安排。 - GPU 工作可以直接进行。使用当前版本的 Windows GPU 驱动程序后,发行版内部即可访问该显卡,因此 CUDA 和 ROCm 工作负载可以使用现有硬件运行。按小时租用同等级 GPU 则需要实际付费。
- 编辑循环更短。文件和浏览器都在本地,因此在
localhost:5173上运行的开发服务器可以直接在已登录的浏览器中打开。
这些都是实际优势,也是通常建议同时使用两台机器而不是只使用一台的原因。
谁负责备份?
两台机器上的备份都由您负责。WSL 中这一点尤其容易让人误解。该发行版是 Windows 用户配置文件中的虚拟磁盘文件(ext4.vhdx)。没有任何提供商会自动为您创建快照。wsl --unregister Ubuntu 会直接删除该文件,无法撤销;重新安装 Windows 时,该文件也会与其他数据一并丢失。请按您确实能够坚持的计划导出:
wsl --export Ubuntu D:\wsl-backups\ubuntu-2026-08-18.tar在 VPS 上,提供商的快照可以保护您免受主机故障影响。但它无法防止您将 rm -rf 放入错误的目录。如果快照与服务器位于同一个账户中,那么账户登录凭据一旦被盗,快照也可能随服务器一起丢失。请将文件级备份推送到服务器之外,并在需要之前先执行一次恢复测试。无论哪种情况,责任都在您。实际区别在于,服务器可以在 03:00 自动推送自己的备份,不需要有人让笔记本保持开机状态。
桥接:从 WSL 通过 SSH 连接 VPS
只有在正确配置连接后,第二台机器才不会成为负担。在 WSL 中完成一次配置即可。
在发行版中生成密钥,不要在 Windows 端生成。这样私钥会保留在具有 Unix 权限的 ext4 文件系统中,ssh 可以接受这些权限:
ssh-keygen -t ed25519 -C "dev@laptop"
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@203.0.113.10Ed25519 密钥短小且速度快,ssh-copy-id 会将公钥以正确的权限追加到服务器上的 ~/.ssh/authorized_keys。SSH 密钥管理基础介绍了之后如何轮换和撤销密钥。
在 ~/.ssh/config 中为服务器设置名称:
Host dev
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ForwardAgent yes
ServerAliveInterval 30现在,ssh dev 会建立连接。IdentitiesOnly yes 会阻止客户端提供它持有的所有密钥。当 agent 中加载了多个密钥时,这可以避免出现 Too many authentication failures。ServerAliveInterval 30 会保持家庭网络连接上的会话,避免会话无提示地断开。
ForwardAgent yes 是让整个流程变得简单的配置项。在笔记本电脑的 agent 中加载密钥后,git clone git@github.com:you/app.git 就能在服务器上工作,而私钥不会落到服务器上。在 VPS 中使用 ssh -T git@github.com 进行测试,正常情况下应返回 Hi you! You've successfully authenticated。只向信任的服务器转发 agent,因为连接期间,该机器上的 root 可以使用您的 agent socket。在与他人共享的服务器上,按仓库配置 deploy key 更安全。
WSL 不会在不同 shell 之间保持 agent 运行,因此每个新终端都会再次要求输入密钥。keychain 可以解决这个问题:
sudo apt update && sudo apt install -y keychain
echo 'eval "$(keychain --eval --quiet id_ed25519)"' >> ~/.bashrc打开新的 shell 并运行 ssh-add -l。它应输出密钥指纹。Error connecting to agent 则表示该行未被读取,请确认 shell 确实加载了 ~/.bashrc。
在服务器上的终端复用器中运行任务,这样连接断开不会终止任务:
tmux new -s dev
# Ctrl-b then d to detach
tmux attach -t dev即使关闭笔记本电脑,构建也会继续运行。这正是使用第二台机器的原因。同样的方法也适用于在 VPS 的 tmux 中运行 Claude Code,之后可以从其他设备重新连接会话。
在部署任何内容前,先加固服务器。新 VPS 上线后的前十分钟会按不会导致您失去访问权限的顺序,介绍非 root 用户、仅使用密钥的 SSH、防火墙和自动安全更新。
哪台机器适合哪类工作?
如果工作主要在当前屏幕上完成,请使用 WSL。例如编辑文件、运行测试套件、在 localhost 上运行开发服务器、使用 notebook、进行 GPU 实验,以及启动后需要持续观察的任务。
如果工作必须对外提供访问,或必须在当前会话结束后继续运行,请使用 VPS。例如客户可以访问的 staging URL、webhook 端点、按实际时间运行的 cron 任务、bot、供其他服务访问的小型数据库,以及在周五下午启动的导入任务。
如果您还在决定第二台机器的用途,人们实际在 VPS 上运行的任务比规格对比更有参考价值,什么是 VPS则解释其底层的虚拟化机制。如果您的工具只能在 Windows 上运行,这是另一个需要单独决定的问题,Linux 与 Windows Server 的对比适合参考。
有一个习惯可以避免两台机器都变成配置不完整的环境:代码存放在 git 中,两台机器都作为该仓库的客户端。任何重要内容都不应只存在于其中一台机器上。
FAQ
我可以在 WSL 中使用真实域名托管网站吗?
不可靠。WSL 2 位于计算机内部的 NAT 后方,路由器还会再执行一次 NAT,而且大多数家庭网络连接都没有可转发的入站端口。隧道服务可以暴露本地端口,但隧道客户端运行在笔记本电脑上,因此笔记本电脑进入睡眠状态时,网站也会停止服务。证书会使问题更加复杂,因为 HTTP-01 challenge 要求 Let's Encrypt 通过公网域名的 80 端口获取文件。具有公网 IP 地址和 A 记录的 VPS 可以同时满足这两个条件,无需变通方案。
systemctl enable 在 WSL 中可以运行吗?
启用 systemd 后即可运行,也就是在 /etc/wsl.conf 中将 systemd=true 设置为 [boot],然后执行 wsl --shutdown。未启用时,systemctl 会回复 System has not been booted with systemd as init system (PID 1). Can't operate.。即使 systemd 正在运行,enable 也只会在发行版启动时启动服务,而发行版是在您打开 shell 时启动的。在服务器上,同一条命令表示重启后服务会自动恢复运行,无需任何用户登录。
为什么我的 WSL IP 地址总是在变化?
在默认 NAT 模式下,虚拟机每次启动时都会从 WSL 虚拟适配器获取一个新的私有地址。任何 netsh interface portproxy 规则或硬编码地址都会在 wsl --shutdown 后失效。使用 ip -4 addr show eth0 检查当前地址。在 Windows 11 上,镜像网络模式会让发行版使用与 Windows 相同的网络接口,从而移除独立地址:在 %UserProfile%\.wslconfig 中将 networkingMode=mirrored 设置为 [wsl2]。
/mnt/c 真的更慢,还是只是误解?
确实更慢。在您自己的计算机上测试 1 分钟即可证明这一点。~ 下的文件位于 ext4 虚拟磁盘中。/mnt/c 下的文件由 Windows 端组件通过 9P 协议提供,因此每次 stat 调用都要跨越边界,而 git status 处理大型目录树时会产生数千次此类调用。将代码仓库复制到 ~,分别在两个位置运行两次 time git status,然后比较预热后的运行结果。将工作副本保存在 ~ 下,并使用编辑器的 WSL 远程模式。
有了 VPS 后,我还需要 WSL 吗?
大多数人会同时保留两者。WSL 免费且启动迅速,因此仍适合用于编辑和测试;GPU 工作也应在这里完成。服务器是持续运行的计算机:它持有公网域名,并运行必须在笔记本电脑关闭后继续执行的任务。将代码保存在 git 中,并将两者都视为代码仓库的客户端,这样在两者之间迁移工作无需额外成本。