VSCode Remote-SSH连接Ubuntu虚拟机:从网络配置到免密登录
2026/9/18 17:03:01 网站建设 项目流程

如果你也是那种"Windows主力干活,Linux虚拟机专门用来跑环境"的玩家,这个需求你大概率遇到过:Ubuntu装好了,代码想放到Linux里跑,但总不能一直在VMware那个小窗口里写吧。复制粘贴不好使、剪贴板不共享、虚拟机一卡,写代码的心情全没了。VSCode远程连接Ubuntu就是解决这个问题的正经路子,核心工具是SSH。这篇文章我把整个流程拆到最细,从虚拟机网络配置、SSH服务开启、VSCode插件安装,到首次连接、报错排查、免密登录和端口转发,全部按"小白照着做就能成"的标准来写。

我见过太多人卡在中间某一步就放弃了,其实这列车的每一节车厢都有明确的检查点,只要按顺序确认好,一次跑通完全没问题。下面开始。

1. 为什么要折腾远程连接:虚拟机里写代码的三个痛点

先说动机。很多人不理解,虚拟机都打开了,Ubuntu桌面也看到了,直接在虚拟机窗口里写代码不就行了?真不行。我用下来的感受是:VMware窗口里写代码的体验,大概处于"能用,但每天都在找罪受"的水平。三个痛点最明显。

第一,界面体验断层。Windows下我习惯了多显示器、多标签页、快捷键切窗口,而虚拟机窗口被限制在一个固定画布里,分辨率还得手动调。更崩溃的是剪贴板经常不同步,我在Windows复制一段代码,切到虚拟机里粘贴,发现是空的,然后又得回头重新复制。这种零碎的摩擦一天下来消耗大量注意力。

第二,性能和资源的双重损失。Ubuntu桌面版本身就吃内存,再叠加上VMware的图形加速,机器差一点就会卡顿。很多时候你只是想跑一个Python脚本或编译一个C程序,根本不需要看到桌面,却被迫养着一个完整的GNOME图形环境。

第三,文件同步绕圈子。也有人用共享文件夹或者Samba在Windows和Linux之间互传代码,但改完代码还得手动同步,再加上编码格式、行尾符差异,经常莫名其妙出bug。

那为什么最终选 VSCode + Remote-SSH?因为它把"编码体验"和"运行环境"拆开了:你仍然在VSCode这个本地编辑器里写代码,但代码实际存放在Ubuntu上,终端、解释器、编译工具、调试器全部跑在远程Linux环境里。下面是几种常见方案的对比。

方案优点缺点适合场景
VMware窗口直接开发零额外配置卡、剪贴板不同步、窗口管理差偶尔用一次
Samba/共享文件夹文件在Windows侧文件同步靠手动,容易冲突传文件
VNC/远程桌面能看到完整桌面网络要求高、延迟明显必须用图形界面
PuTTY + XShell轻量稳定纯终端,编辑体验弱运维服务器
VSCode Remote-SSH本地编辑体验,远程执行环境首次配置稍复杂日常开发主力

结论很直接:如果是正经写代码,Remote-SSH是当前综合成本最低的方案。剩下的问题就是,怎么把它跑通。

2. 动手前把三件事理清楚:网络、SSH服务、客户端

很多人上来就装VSCode插件,然后连不上,再回来查问题。我的经验是,先把底层链路理清楚,最后再碰VSCode。这条链路从上到下依次是:虚拟机网络、Ubuntu的SSH服务、Windows侧的SSH客户端和VSCode插件。每一层都有独立的验证方法。

2.1 虚拟机网络怎么选:NAT是默认最优解

Ubuntu能上网,不代表宿主机能直接连到它。这是新手最容易踩的第一个认知误区。虚拟机有三种常见网络模式,我用VMware和VirtualBox都测过,结论一致。

  • NAT模式(VMware里叫NAT,VirtualBox里叫NAT):虚拟机通过宿主机共享IP上网,对外表现为宿主机的一个内部设备。宿主机可以主动访问虚拟机,虚拟机的出站网络也通。适合大多数开发场景。
  • 桥接模式(Bridged):虚拟机和宿主机在同一个局域网里,有自己的独立IP,看起来就像另一台实体机。适合需要被局域网其他人访问的场景。
  • Host-Only模式:虚拟机只能和宿主机通信,不能上网。只适合做隔离实验。

对小白来说,默认选NAT就对了。理由很简单:NAT不需要关心路由器配置,不用担心同事的电脑IP占用,虚拟机的IP由VMware内部DHCP分配,宿主机访问它是稳定可控的。桥接模式虽然听起来更"真实",但一旦换了Wi-Fi或网线,虚拟机的IP可能变,反而麻烦。

装好Ubuntu后,在虚拟机里打开终端,执行ip addr查看IP地址,类似192.168.xxx.xxx这种。这里有个小坑:很多人用ifconfig,但新版本Ubuntu默认没装net-tools,会提示command not found。直接ip addr就行,这是现代Linux标准的网络查询命令。

提示:判断虚拟机网络是否正常的快速方法是ping www.baidu.com,能通说明出站网络没问题。但别忘了,出站正常和宿主机能连它,是两码事。

2.2 Ubuntu开启SSH服务

Ubuntu默认只装了SSH客户端,没有服务端。也就是说,它能用ssh去连别人,但别人连不上它。所以必须要装openssh-server

在Ubuntu终端里按顺序执行:

# 先更新软件源缓存 sudo apt update # 安装SSH服务端 sudo apt install -y openssh-server

装完后,用下面三条命令确认状态:

# 查看SSH服务状态 sudo systemctl status ssh # 开机自启 sudo systemctl enable ssh # 确认22端口在监听 ss -tlnp | grep 22

如果最后一条命令能看到0.0.0.0:22[::]:22的监听记录,说明SSH服务已经正常起来了。再看一眼Ubuntu自带的防火墙:

sudo ufw status

如果你之前手动开过UFW防火墙,状态是active,记得放行22端口:

sudo ufw allow ssh

这一步很多人会忘,但SSH连不上的错误里,有一小半其实是防火墙在拦。

2.3 宿主机安装VSCode和Remote-SSH插件

VSCode安装没什么难点,记住从官方网站下载。Windows下安装时有个选项叫"添加到PATH",建议勾上。安装完后搜索插件Remote - SSH,这是微软官方出的扩展,扩展ID是ms-vscode-remote.remote-ssh,认准这个ID,同名仿冒的插件很多。

装好插件后,VSCode左下角会出现一个绿色或蓝色的><图标。这个图标是Remote开发的入口,后面所有连接操作都从它出发。

顺便提一句,如果你之前按网上的教程装了一堆其他远程插件,比如Remote - SSH: Editing Configuration Files这类,它们是Remote-SSH的辅助扩展,不用单独装,主插件会自动带上。

到这里,底层三件事全部就绪。检查清单是:虚拟机网络通不通、SSH端口在不在监听、VSCode插件装没装好。三件事都确认后,再进入真正的连接环节。

3. 从配置到第一次连接成功:每一步都有产出

配置过程其实就两件事:写SSH配置文件,然后发起连接。但这两件事里的细节决定成败。

3.1 一份不会出错的SSH Config

在VSCode里按F1Ctrl+Shift+P打开命令面板,输入并执行:

Remote-SSH: Open SSH Configuration File...

这时会让你选择配置文件,Windows下默认路径是C:\Users\你的用户名\.ssh\config。如果弹出提示说文件不存在,选择"创建新文件",然后把它保存到这个路径。

把下面这段配置写进去:

Host ubuntu-vm HostName 192.168.xxx.xxx User yourname Port 22

解释一下每个字段:

  • Host:给这个连接起的别名,随便写,方便自己认就行。后面连接时选这个名字。
  • HostName:Ubuntu的IP地址,就是刚才用ip addr查到的那个。
  • User:你登录Ubuntu时用的用户名,不是邮箱,也不是显示名,是类似于yourname的那个短名称。可以通过执行whoami查询。
  • Port:SSH端口,默认就是22,写不写都可以,但写上更清晰。

注意:Windows下如果你之前没建过.ssh文件夹,直接创建C:\Users\你的用户名\.ssh\config即可。但如果你用的是老版本Windows或公司电脑有安全策略限制,建议把路径放在VSCode提示的默认位置,不要随意改到其他盘。

3.2 发起首次连接,遇到fingerprint怎么选

配置写好后,再按F1,执行:

Remote-SSH: Connect to Host...

选择刚才配置的别名ubuntu-vm。VSCode会新开一个窗口,然后开始连接流程。首次连接时,界面会弹出一个对话框,内容是:

The authenticity of host '192.168.xxx.xxx' can't be established. Are you sure you want to continue connecting?

这是SSH在问你:这台主机的指纹(fingerprint)不认识,是否信任它并继续连接?输入yes回车即可。原理很简单——SSH防止"中间人攻击",首次连接时记录主机指纹,以后再连会校验。如果你不确定,可以先把Ubuntu上执行ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub得到的指纹拿出来对照一下,确认一致再输yes。

接下来会提示输入密码。这里输入的密码是没有回显的,屏幕上不会显示任何字符,这是正常的,不要以为键盘坏了。输完回车,VSCode会在线安装vscode-server到远程Ubuntu,这个过程视网络情况需要几十秒到几分钟。

连接成功的标志是左下角显示SSH: ubuntu-vm,同时底部状态栏变成绿色。

3.3 验证连接不是"表面成功"

这一步很多人省略,但我觉得必须做,因为"VSCode不报错"和"确实能在远程干活"是两回事。

连接后先做三件事:

  1. 打开远程文件夹:File->Open Folder,此时弹出的文件浏览器会让你输密码,然后看到的是远程Linux的文件系统。随便打开一个文件夹,比如/home/你的用户名
  2. 打开集成终端:快捷键Ctrl+`,执行whoamiuname -a。如果输出的是Ubuntu的用户名和Linux内核信息,说明终端确实跑在远程机器上。
  3. 安装一个远程扩展,比如Python。打开扩展面板,搜索Python,点击Install in SSH: ubuntu-vm。装好后,在扩展列表里能看到这个插件被归到SSH: ubuntu-vm分类下,而不是本地。

这三步走完,才算是真正跑通了远程开发链路。

4. 一键复现排错现场:连接失败的完整排查链

这一节写给那些"第一次没成"的朋友。我把自己见过的所有失败案例按排查顺序整理成了一条链路,从网络层一路往上到应用层。别跳着看,按照这个顺序找,问题在哪里一目了然。

4.1 连接超时或卡在"Setting up SSH Host"

如果在选择的瞬间就报Could not establish connection to ...或者长时间卡在转圈状态,第一个要怀疑的是网络层,不是VSCode

先到Windows的PowerShell或CMD里执行:

ping 192.168.xxx.xxx
  • 如果能ping通,说明宿主机和虚拟机之间网络通着,继续往下排查。
  • 如果ping不通,问题在虚拟机网络。检查VMware菜单里的"可移动设备"或"虚拟机设置",确认网络连接是NAT模式且已连接。再回到Ubuntu里看一眼IP是否变了。
  • 如果ping能通但SSH连不上,执行Test-NetConnection 192.168.xxx.xxx -Port 22,Windows下这个命令可以快速判断22端口是否可达。

一个很容易踩的坑:虚拟机休眠或者VMware挂起后再恢复,IP可能变了。每次连不上,先重新ip addr确认一遍IP,再把config里的HostName改掉。为了从根上解决这个问题,我后面会在进阶部分说固定IP的方法。

4.2 Permission denied (publickey,password):用户名和密码验证

这个报错说明网络和端口都通,但SSH身份验证没过。先看报错里的细节:

  • Permission denied, please try again.:通常是密码错了,或者用户名写错了。
  • Permission denied (publickey,password).:SSH服务器拒绝了基于密码的登录,只允许密钥登录。

查三处:

  1. 确认config里的User字段。注意,不是root就能无障碍登录,很多Ubuntu默认禁止root远程登录,要用普通用户名。
  2. 确认密码是否正确。Ubuntu安装时设置的用户密码,不是某些工具里显示的动态密码。
  3. 检查远程的sshd配置。执行:
sudo grep -E "PasswordAuthentication|PermitRootLogin" /etc/ssh/sshd_config

正常应该看到PasswordAuthentication yes。如果看到的是no或这一行被注释掉了,就用sudo nano /etc/ssh/sshd_config打开,取消注释并改成yes,然后执行sudo systemctl restart ssh重启服务。

4.3 连接后立刻退出或反复要求密码

这种症状是:密码输对了,连接建立起来了,但两秒后自动断开,或者要求重新输密码。这类问题,九成出在远程家目录的权限上。

SSH服务端对权限非常敏感:如果~/.ssh~/.ssh/authorized_keys权限过于开放,会被直接拒绝。执行下面两条命令修正:

chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys

如果你压根没建过.ssh目录,则先创建再设置权限:

mkdir -p ~/.ssh chmod 700 ~/.ssh touch ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys

另一类常见原因是Windows侧的known_hosts里记录了同一个IP但不同的指纹。比如Ubuntu重装系统后,SSH host key变了,Windows还保留着旧记录,连接就会直接报REMOTE HOST IDENTIFICATION HAS CHANGED。解决办法是找到C:\Users\你的用户名\.ssh\known_hosts,删除对应IP的那一行,重新连接。

4.4 "此扩展在此工作区中被禁用,因为其被定义为在远程扩展主机中运行"

这个提示很搞心态,我初次遇到的时候也懵了。它的本质是:VS Code的扩展分两类,一类是本地UI扩展(比如主题、快捷键增强),一类是需要在远程主机上运行的扩展(比如Python语言服务、VS Code Server端插件)。Remote-SSH会自动决定每个扩展应该装在哪一侧。

当你看到"被定义为在远程扩展主机中运行"的禁用提示,通常是因为你在本地安装了某个扩展,但它的manifest里声明了extensionKind: ["remote"],导致VSCode自动把它标记为"远程扩展",而你又没有连接到远程,于是被禁用。

解决办法很简单:

  1. 连接远程成功后再安装这个扩展,选择Install in SSH: ubuntu-vm
  2. 已装在本地但被禁用的,在扩展面板里找到它,点击齿轮,选择设置为远程扩展,或者干脆点禁用,然后重新连接远程再启用。

这个问答在官方issue里出现过很多次,其实不是bug,是设计的扩展归类机制,理解了就不慌。

4.5 其他高频报错速查表

我整理了一个表,覆盖了我试过Remote-SSH以来遇到的其他高频问题。

报错或现象主要原因先试的解法
Could not establish connection to "xxx"网络不通或host配置错误ping宿主机、验证config文件
Port 22: Connection timed out防火墙或端口未监听检查ss -tlnpufw status
REMOTE HOST IDENTIFICATION HAS CHANGEDknown_hosts记录旧的host key删除known_hosts中对应行
vscode-server: 下载失败/超时远程~/.vscode-server损坏或网络问题删除~/.vscode-server后重新连接
远程终端中文乱码远程locale未设置执行export LANG=en_US.UTF-8并写入~/.bashrc
Bad owner or permissions on ~/.ssh/configWindows下config权限过大右键文件属性-安全-完全控制只留当前用户
连接成功但打开目录失败远程目录权限不够使用有权限的用户或chmod

排查问题的总体原则:从链路底层往上查。网络层不通就别折腾SSH,SSH服务没起来就别怪VSCode,VSCode能连上但扩展报错再去查扩展。按照这个顺序来,绝大多数情况都能快速定位。

5. 连上之后怎么把体验拉满:免密、转发、开发习惯

跑通是第一步,真正好用的是把后续体验优化到位。这一节我选了三个投入产出比最高的优化点。

5.1 SSH密钥免密登录:省掉每次输密码

每次连接都输密码,次数多了就烦。SSH密钥登录是一次配置、永久受益的操作。原理很简单:把本地生成的一把公钥放到远程主机的~/.ssh/authorized_keys里,之后本地发起SSH请求时,远程用公钥验证你的私钥,密码环节就省了。

在Windows的PowerShell或CMD里执行:

ssh-keygen -t ed25519 -C "windows-local"

一路回车即可,默认保存到C:\Users\你的用户名\.ssh\id_ed25519。然后执行:

type C:\Users\你的用户名\.ssh\id_ed25519.pub | ssh ubuntu-vm "cat >> ~/.ssh/authorized_keys"

这条命令的意思是把本地的公钥内容追加到远程的授权列表中。执行完会要求输入一次密码,之后就永久免密了。验证方式是直接执行ssh ubuntu-vm,不再需要密码。

提示:免密登录后,VSCode的Remote-SSH也会自动继承这个能力,连接时不会再弹密码框,体验接近本地开发。注意备份好私钥文件,它就是你的登录凭证,丢了没法通过远程找回。

5.2 端口转发:在Windows浏览器里打开虚拟机里的服务

连接成功只是开始。你在Ubuntu里跑一个Web服务、Jupyter Notebook,或者调试一个后端API,总不能每次都去看虚拟机IP加端口吧。Remote-SSH内置了端口转发功能,可以直接把远程端口"搬到"本地。

最常见的场景:Ubuntu里启动一个开发服务器,端口是8000,希望在Windows浏览器里直接访问http://localhost:8000

在已连接的VSCode窗口里,找到"端口"面板(Ports),点击端口输入框,填8000,回车。VSCode会自动创建转发。接着在Windows浏览器打开http://localhost:8000,就能访问到远程服务了。

另一种更持久的方式是写进SSH Config里:

Host ubuntu-vm HostName 192.168.xxx.xxx User yourname Port 22 LocalForward 8000 localhost:8000

这样每次连接都会自动把远程8000端口映射到本地8000端口。

5.3 把虚拟机当成开发机的三条建议

真正把Remote-SSH用起来之后,会有种"Windows是我的编辑器,Ubuntu是我的编译器"的感觉。给你三个我用下来觉得很值的配置建议。

第一,先拍快照再乱动。VMware支持虚拟机快照,所有配置操作、系统更新之前,先拍个快照,出问题了秒回。这是远程开发最大的安全感来源。

第二,固定虚拟机IP。DHCP虽然省事,但IP变了就得改config。最简单的方法是在路由器里给虚拟机MAC地址绑定固定IP,或者在Ubuntu里手动配置Netplan。对纯内部开发,我建议直接编辑/etc/netplan/下的yaml文件,把dhcp4: no并配置静态IP,改完sudo netplan apply生效。

第三,日常开发优先走Remote-SSH。很多情况下不需要打开VMware窗口,VSCode远程连接后台虚拟机就能完成开发。VMware窗口可以最小化甚至让虚拟机后台运行,节省宿主机资源。如果仅需要命令行,也可以直接用ssh ubuntu-vm登录终端。

最后再分享一个我自己的使用体会。远程连接受网络、SSH服务、密钥、VSCode四个层面的共同影响,出问题时不要慌,按照"网络层 → 服务层 → 配置层 → 应用层"这个顺序排查,大部分问题十分钟内都能定位。很多人把它想复杂了,其实链路并不长,关键是每一步都要有验证意识。真到了连串行流程都跑通的那天,你会发现,敲代码的最佳姿势就是在Windows里开着VSCode,而所有的运行和调试都在那台安静的Ubuntu虚拟机里完成。这个配置值得花半小时搞定,因为之后每天写代码都在享受它。

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

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

立即咨询