ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

VS Code Remote-SSH 连接失败排查:分层定位与配置实践

VS Code Remote-SSH 连接失败排查:分层定位与配置实践 上周同事发来一张截图左边是 VS Code 卡在Setting up SSH Host xxx的转圈提示右边是终端里一行冷冰冰的Connection refused。他的原话是密钥配好了昨天还能连今天什么都没动。这句话我大概听过几十遍而每次真正的原因都不在密钥上——有人是服务端 sshd 重启后没起来有人是网络出口策略变了有人是家目录写满导致远端组件解压失败还有人只是~/.ssh/config里多敲了一个空格。VS Code 的 Remote-SSH 是个特别好用、也特别容易让人误判的工具。它把 ssh 连接、远端组件分发、端口转发、扩展宿主启动这一整套流程打包成了一个连接到主机的按钮。一旦失败界面上给的提示往往只有一句Could not establish connection to xxx这句话几乎等于没说它可能是网络不通可能是认证被拒可能是登进去了但服务端组件跑不起来甚至可能只是某个扩展的提示被误读成了连接错误。下面这篇东西我想按故障分层的方式把这几年踩过的坑摊开讲一遍从明确 Remote-SSH 到底做了哪几件事开始到命令行优先的定位方法再到认证、服务端部署、配置文件写法最后是那些被误认为连接失败的杂项问题。命令基于 openssh 客户端和 Linux 服务端Windows 客户端会用自带 OpenSSH 的写法macOS 基本一致。不管你是刚装完 VS Code 想连实验室机器还是手里管着十几台跳板机应该都能在里面找到对应的排查路径。1. 先把故障分层Remote-SSH 一次连接究竟做了哪几步1.1 它不是黑盒本质是替你调用了系统的 ssh 客户端很多人把 Remote-SSH 当成一个内置了网络功能的插件所以一出错就去翻插件设置其实方向从一开始就偏了。你在 VS Code 里点连接到主机它做的事情大致是解析~/.ssh/config和你在命令面板里输入的主机名拼出一条 ssh 命令行然后调用本机系统里那个 ssh 可执行文件去建立连接。这意味着两件很重要的事。第一VS Code 能不能连上取决于你系统里的 ssh 客户端本身能不能连上跟插件版本关系不大。第二你在终端里ssh 主机名用什么路径、什么密钥、什么参数VS Code 走的也是同一套逻辑如果终端里连不上别指望 VS Code 能连上。Windows 上这一点尤其容易乱。Win10 1809 之后系统自带 OpenSSH 客户端路径在C:\Windows\System32\OpenSSH\ssh.exe但如果装过 Git for Windows它也会带一个ssh.exe通常在C:\Program Files\Git\usr\bin\ssh.exe。这两个是不同的实现读的配置文件位置也可能不同。踩过的坑是你在 Git Bash 里配好了密钥终端里能连VS Code 却一直提示认证失败原因就是 VS Code 调用的是系统那个 ssh而系统那个的~/.ssh指向的是C:\Users\你的用户名\.ssh跟你以为的目录不是一个。想知道 VS Code 到底用了哪个 ssh最快的办法是打开命令面板搜索Remote-SSH: Show Log在日志里能看到它实际执行的命令和使用的 ssh 路径。1.2 三段式连接模型能通、能登、能跑排除掉插件本身的 bug一次远程连接可以稳定地切成三段每一段的失败原因完全不同第一段是传输层可达。本机能不能路由到目标主机目标主机的 22 端口或自定义端口有没有程序在监听中间有没有防火墙、安全组、网络策略把它拦掉。这一段的典型报错是Connection refused、Connection timed out、No route to host、Network is unreachable。第二段是认证通过。TCP 通了双方开始协商服务端问你要凭据你给的密钥或者密码能不能过。典型报错是Permission denied (publickey)、Authentication failed、Too many authentication failures。第三段是服务端就绪。认证过了你确实登上了那台机器但 VS Code 还要在远端下载并启动一套vscode-server组件再通过一条反向转发把本地编辑器和远端服务接起来。典型表现是卡在Setting up SSH Host、Downloading VS Code Server、正在打开远程最后弹一句超时或者直接断连。很多人排查效率低就是因为跳过了这个分层拿第三段的症状去改第二段的配置。比如远端家目录满了导致组件解压失败屏幕上显示的却是Could not establish connection看起来像连不上实际早就登录成功了。1.3 报错关键字与责任层的对照表把常见提示和它真正对应的层级对起来能省掉大量试错时间界面/终端提示关键字大概率所在层级优先检查的东西Connection refused传输层目标端口是否监听、sshd 是否运行Connection timed out/No route to host传输层地址是否正确、网络策略、是否只在特定网段可达Permission denied (publickey)认证层公钥是否在服务端、权限、用户名REMOTE HOST IDENTIFICATION HAS CHANGED认证层服务端主机密钥变更需要清理 known_hosts 条目Too many authentication failures认证层本地密钥太多服务端一次只允许试几次Setting up SSH Host长时间不动服务端就绪组件下载失败、磁盘空间、架构不匹配连上后立刻断开并反复重连服务端就绪shell 启动脚本污染、/tmp权限、内存不足此扩展在此工作区中被禁用根本不是连接问题扩展被定义为只在远端运行的误读这张表我自己是贴在便签上的遇到问题时先看提示落在哪一行能直接砍掉一半的无效排查。2. 别急着改配置先按命令行优先原则定位2.1 输出面板里的 Remote-SSH 日志才是第一现场VS Code 的图形界面会隐藏掉 90% 的信息。真正有用的第一手材料在输出面板里菜单栏查看 → 输出右上角的下拉框里选Remote - SSH或者在命令面板里执行Remote-SSH: Show Log。这个日志里能看到完整的 ssh 调用记录包括它用的是哪个 ssh 可执行文件、传了哪些参数、服务端返回了什么。常见的有效信息有这几类服务端返回的原始错误串比如Permission denied (publickey,gssapi-keyex,gssapi-with-mic)这比界面上的提示精确得多Identity file之类的行能确认它到底加载了哪把私钥远端组件的路径和版本号比如~/.vscode-server/bin/commit-id卡住时可以直接去这台机器上看这个目录是否存在、是否解压完整连接阶段的时间戳能判断是根本没连上还是连上很久之后才断。一个很实用的小技巧日志面板里右键有清除输出先清空再重新点一次连接这样看到的就纯粹是本次连接的完整过程不会被之前的残留干扰。2.2 在系统终端裸跑 ssh把 VS Code 从变量里摘出去接下来这一步是我强烈建议所有人养成的习惯不要一上来就在 VS Code 里反复点重试先打开系统终端跑一条裸命令。ssh -vvv -p 22 用户名主机地址-vvv是最高级别的调试输出会把连接过程分成清晰的三段打印出来先是一堆debug1: Connecting to ...然后是密钥交换和认证协商最后是debug1: Authentication succeeded或者认证失败的具体原因。看的时候不用逐行读只要记住三个关键节点Connecting to ip port 22之后如果很快出现Connection refused是端口或服务问题如果是connect to host ... port 22: Connection timed out是网络可达性问题先别碰 ssh 配置如果一路走到Authentications that can continue:然后又失败问题在认证重点看它列出了哪些可接受的认证方式。如果-vvv的输出里出现了Offering public key: /home/you/.ssh/id_rsa这样的行说明它确实在尝试某把密钥而紧接着Authentications that can continue: publickey说明服务端拒绝了它。这时候要查的就是这把密钥对应的公钥有没有正确放进服务端的~/.ssh/authorized_keys。裸跑命令能连上的话再回到 VS Code重点就变成两者用的 ssh 或配置不一样通常几分钟就能找到差异。裸跑也连不上那 VS Code 的一切界面操作都是白费力气。2.3 服务端 sshd 状态与端口监听的两条命令如果确认是传输层问题而你有办法通过其他途径比如云服务商的控制台、本地虚拟机的窗口登进那台机器那就在服务端跑两条命令systemctl status ssh ss -tlnp | grep ssh第一条看服务是不是在跑、有没有报错、最近有没有重启过。Ubuntu 上服务名常见的是ssh有些发行版是sshd两个都试一下或者用systemctl list-units | grep ssh找。第二条看它监听的地址和端口。这一条经常能抓到我明明配了 2222 端口但连不上的问题——ss输出里的第一列如果是127.0.0.1:22说明 sshd 只监听了本机回环地址外部根本连不进来正常应该是0.0.0.0:22或者*:22。对应的配置项在/etc/ssh/sshd_config里的ListenAddress很多时候是被某次安全加固顺手改成了127.0.0.1改完忘了改回来。改完配置记得先用sshd -t校验语法再systemctl restart ssh。直接重启一个语法错误的配置会把你自己彻底关在门外这一点后面还会再强调。2.4 端口连不通时先确认路径上谁在拦确认服务端监听正常、客户端还是timed out那就不是 ssh 的问题而是这条路径上某一段被挡住了。按从近到远的顺序确认本机网络能不能 ping 通目标地址。注意很多云主机默认禁 ICMPping 不通不代表端口不通所以别只看 ping 结果就下结论。端口连通性用nc -vz 主机地址 22macOS 自带是nc -v -z或者 Linux 上timeout 5 bash -c /dev/tcp/主机地址/22能建立连接就说明端口是通的。Windows PowerShell 上用Test-NetConnection 主机地址 -Port 22它会直接告诉你是TcpTestSucceeded : True还是False。云平台安全组这是最常见的拦路虎。很多云主机默认只放行 22 给特定来源地址你换了个网络出口就连不上。这个必须在控制台里看从机器内部再怎么折腾也没用。服务端本机防火墙iptables -L -n或者ufw status。有些场景下前面那层放行了机器自己的防火墙没放行表现完全一样。我自己的习惯是把可达性这一步彻底做完再碰认证因为这两类问题的修复手段完全不重叠混在一起查只会让排查过程变成随机试错。3. 卡在认证阶段密钥、权限与指纹的三类典型事故3.1 公钥投递错位置authorized_keys 的常见写法错误Permission denied (publickey)出现时八成是公钥没到位。先把本地的公钥打印出来cat ~/.ssh/id_ed25519.pub然后确认服务端~/.ssh/authorized_keys里的内容。这里有三个高频错误第一贴了私钥。有人cat id_ed25519不带.pub把私钥内容粘进了 authorized_keys。私钥是-----BEGIN OPENSSH PRIVATE KEY-----开头的长块公钥是ssh-ed25519 AAAA...开头的一行。粘错了不仅连不上还等于把私钥泄露到了服务端必须立刻重新生成一对。第二粘贴时被自动换行。公钥是一整行中间不能有换行。用某些终端复制时会被硬折行结果 authorized_keys 里变成两行sshd 解析不了。判断方法是数一下wc -l ~/.ssh/authorized_keys每个公钥应该只占一行。第三追加时用了而不是。cat id_ed25519.pub authorized_keys会把原有内容全部覆盖掉如果这台机器上还有别的公钥在用一起遭殃。养成习惯追加一律用。追加完建议顺手看一眼权限这一条下一节展开。3.2 权限过松sshd 直接忽略你的密钥ssh 对权限的严格程度经常让人莫名其妙文件内容完全正确就是登不上日志里还看不出原因。这是 sshd 的StrictModes机制在起作用——它对家目录、.ssh目录、authorized_keys有一套权限要求不满足就直接跳过这个文件而且不会主动告诉你为什么。标准权限是这样的chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chmod 700 ~最后一条容易被忽略。如果家目录本身是 777sshd 会认为别人可以往里写文件从而拒绝使用这里的密钥。诊断时直接跑ls -ld ~ ~/.ssh ~/.ssh/authorized_keys输出里如果出现drwxrwxrwx或者属主不是你自己那就是问题所在。属主不对的情况常见于用 root 创建了.ssh目录之后没改回来修复方式是chown -R 用户名:用户名 ~/.ssh。服务端日志里如果能看到Authentication refused: bad ownership or modes for file这类行基本可以确诊。日志一般在/var/log/auth.logDebian/Ubuntu 系或者/var/log/secureRHEL 系用tail -f盯着再重试一次连接效果最好。3.3 known_hosts 指纹变更与 StrictHostKeyCheckingWARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!这个报错看上去最吓人实际上含义很单纯服务端的主机密钥变了而你本地缓存的还是旧的。主机密钥为什么会变重装系统、重新生成密钥、换了一台机器但 IP 沿用了、容器重建都会导致这个结果。也有一种情况需要警惕网络中间有人在拦截。不过在日常开发场景里绝大多数就是重装或者迁移。确认机器确实是你自己的之后清理旧记录ssh-keygen -R 主机地址如果是自定义端口要带上方括号格式ssh-keygen -R [主机地址]:2222。执行完再连一次会提示你确认新的指纹。测试阶段如果不想每次都手动确认可以在命令行临时加上-o StrictHostKeyCheckingaccept-new。这里我要说一句不要把它当成长期方案写进全局配置。这个参数关掉的是对服务端身份的校验日常连开发机无所谓但如果这台机器上跑着有权限的东西它让中间人拦截变得更容易。养成手动核对指纹的习惯成本只有几秒钟。还有一个隐蔽的坑Windows 上 VS Code 用系统 OpenSSH、终端用 Git 自带的 ssh 时两者的 known_hosts 是两份。可能出现终端里清理过了VS Code 依然报指纹变化的诡异现象。解决办法是在 VS Code 日志里确认它使用的 ssh 路径然后去对应的C:\Users\你的用户名\.ssh\known_hosts里处理。3.4 服务端禁用密码登录本地却还在走密码很多服务器为了安全会在sshd_config里设PasswordAuthentication no。这本身没问题但如果客户端没有可用密钥表现就是一直弹密码框、一直失败或者直接Permission denied。排查动作很简单先看服务端允许哪些认证方式grep -Ei PasswordAuthentication|PubkeyAuthentication|PermitRootLogin /etc/ssh/sshd_configPubkeyAuthentication yes说明密钥可用那就往密钥方向查如果PasswordAuthentication no而你又没有密钥只能让管理员临时打开密码登录并配置密钥配好后再关掉。这里顺带说一个踩过两次的坑PermitRootLogin如果设成no用 root 直连一定失败不管你密钥多正确。正确做法是用普通账号登录后再sudo。VS Code 在远端执行的很多操作也需要普通用户权限 免密 sudo 配置这一点在后面第 6 节会结合实际场景再讲。3.5 一次连接里塞了太多密钥导致的 Too many authentication failures本地~/.ssh目录下如果躺着一堆密钥工作用的、个人项目用的、给别人配的ssh 客户端默认会依次尝试而服务端的MaxAuthTries通常是 6。试到第 6 次还没成功服务端直接断开你会看到Too many authentication failures。解决方式有两种。一种是显式指定密钥不让它乱试ssh -i ~/.ssh/id_ed25519_work -o IdentitiesOnlyyes 用户名主机地址另一种也是我更推荐的是把配置写进~/.ssh/configHost work-server HostName 192.0.2.10 User deploy Port 22 IdentityFile ~/.ssh/id_ed25519_work IdentitiesOnly yesIdentitiesOnly yes这一行是关键它让客户端只用这个 Host 段里指定的密钥不再逐个试目录下的其他钥匙。加上它之后我还有过另一个意外收获原本因为试错太多而需要两三秒的连接变成了一次成功体感上快了不少。4. 登进去了却卡住远端 vscode-server 的部署问题4.1 server 组件下载失败与离线安装包的正确用法认证通过、终端能正常登录但 VS Code 卡在Setting up SSH Host或者Downloading VS Code Server这是第三段里最常见的一类。本质是VS Code 要在远端机器上下载一份和本地版本严格对应的服务端组件放在~/.vscode-server/bin/commit-id/下。下载这一步失败了。失败原因通常是目标机器访问不了组件分发的地址或者下载过程中断。这时有两个可走的路径。路径一是让目标机器能访问到下载源。如果这台机器本身网络正常多半只是临时抖动重试一次就好。路径二是离线安装这个更可靠。做法是先在本地通过 VS Code 日志或者远端目录里的 commit id 确认需要哪个版本然后在能上网的机器上把这个组件包下载下来传到目标机器的对应目录解压、确认目录结构。有一个细节要特别注意组件包解压后的目录名必须是 commit id而且解压出来的可执行文件要有执行权限。上传解压后记得chmod x一下。之前遇到过有人把包解压到~/.vscode-server/下面变成多套了一层目录VS Code 找不到表现是继续卡在下载提示。还有个清理动作值得记住怀疑远端组件状态坏了的时候直接删掉重来是最快的。rm -rf ~/.vscode-server删掉之后重新连接会触发一次干净的重装。这个操作的成本就是重新下一次组件比在残缺状态上反复折腾效率高得多。4.2 glibc 版本与 CPU 架构不匹配服务端组件的运行对系统环境有要求主要卡在两个点CPU 架构和 glibc 版本。架构问题现在越来越常见因为不少人手里有 ARM 的服务器或者开发板而远端组件的架构版本需要和本机框架严格对应。如果目标机器是 ARM64而你装的是 x86 构建组件根本跑不起来。判断方法很直接uname -m ldd --version | head -n 1uname -m输出aarch64就是 ARM64x86_64是常见的服务器架构。glibc 的问题主要出现在一些精简系统或较老的企业发行版上。服务端组件依赖较高版本的 glibc如果系统自带的版本太旧启动时会报类似GLIBC_2.28 not found的错误。这种错误在 VS Code 界面里通常只显示成一句笼统的连接失败必须去看远端的日志才能发现。一些国产桌面 Linux 发行版上也踩过类似的坑系统自带的软件源版本偏旧依赖链不好满足。这种情况下比较现实的做法是升级系统或者改用容器化的开发环境——在目标机器上跑一个干净的容器把 ssh 打进容器里让 VS Code 连容器而不是连宿主机。这样做还有一个额外好处宿主机的各种历史包袱完全不影响开发环境。4.3 /tmp 不能执行、家目录写满、磁盘配额这一类问题最容易被忽略因为从任何界面提示上都看不出来。/tmp挂载了noexec。有些安全加固方案会把/tmp挂成不可执行而服务端组件在启动过程中会在/tmp里放临时文件并执行。检查方式mount | grep -w /tmp输出里如果有noexec就说明是它。临时验证可以用mount -o remount,exec /tmp但重启后会恢复长期方案是改/etc/fstab或者调整安全策略。家目录写满。服务端组件本身占几十到上百 MB加上日志和索引占用还会往上走。df -h ~看一下使用率。这个坑我印象很深有台机器因为远端日志文件把盘写满所有用户的远程连接全部失败表现是昨天好好的今天都连不上排查了半天才发现和 ssh 配置一点关系都没有。磁盘配额。部分服务器会对每个用户设 quota。quota -s可以看当前用量。如果配额很小服务端组件装不下去同样会卡在部署阶段。4.4 shell 启动脚本里的 echo 会污染整个协议这是一个非常隐蔽但很有代表性的问题登录本身成功了人也能在终端里正常敲命令VS Code 却一直连不上或者连上就断。原因是 ssh 的远程执行通道依赖 stdout 传协议数据。如果你在~/.bashrc、~/.bash_profile、~/.profile里写了echo 欢迎登录或者一些打印命令输出的脚本这些内容会混进协议流里把 VS Code 的握手搞乱。判断方法很直接把登录时的输出掐掉试试ssh -T 用户名主机地址 echo ok如果这条命令的输出除了ok还有别的东西那就是启动脚本在污染。修法是把echo都改到交互式判断里面去if [[ $- *i* ]]; then echo 欢迎登录 fi这样只在交互式 shell 里打印非交互式的远程执行通道就不会被污染。顺带说一句同样的道理也适用于那些会在登录时跑很多命令的脚本——不仅污染输出还会让每次远程连接都慢上好几秒。我见过最夸张的一台机器登录时执行了一段遍历大目录的统计脚本导致 VS Code 每次连接都要等将近二十秒。5. 配置文件里的细节一份 config 写对胜过十次重试5.1 最小可用配置逐行拆解~/.ssh/config是值得花时间学一次的文件它的语法简单但细节多。一个最小但完整的 Host 段长这样Host myserver HostName 192.0.2.10 User deploy Port 2222 IdentityFile ~/.ssh/id_ed25519_work IdentitiesOnly yes逐行说清楚Host是你自己起的别名之后ssh myserver和在 VS Code 里填的都是它。别名不参与网络解析随便起但建议用有意义的名字。HostName才是真正的地址可以写 IP 也可以写域名。User是登录用户名。省掉它的话ssh 会用你本机的当前用户名这在跨系统时几乎必错——本地是zhangsan服务端账号是deploy不写就是登录失败。Port只在非默认端口时写。IdentityFile指定私钥路径。这里的~在 Linux/macOS 上有效Windows 上建议写完整路径。IdentitiesOnly yes前面说过避免逐个试钥匙。写完保存先别急着开 VS Code在终端里ssh myserver验证一次。终端能通再用别名在 VS Code 里连接这样万一出错你至少知道问题不在网络和认证上。5.2 跳板机多级跳转的写法与常见坑需要经过一台中转服务器才能到目标机器时配置里用ProxyJumpHost jumpbox HostName 203.0.113.5 User ops IdentityFile ~/.ssh/id_ed25519_ops Host target HostName 10.0.0.21 User deploy Port 22 ProxyJump jumpbox IdentityFile ~/.ssh/id_ed25519_work这里有两台机器的密钥优先级问题容易被搞混连接target时客户端会先用jumpbox段的配置去连中转机再用target段的配置连目标机。如果中转机和目标机用的是同一把密钥可以在target里再写一次也可以依赖 ssh 的默认密钥发现逻辑但更稳妥的做法是显式写清楚然后用-v验证一遍它到底加载了哪把。VS Code 对ProxyJump的支持是完整的配置写好之后直接连target别名即可。但有一个坑要提醒中转机上不要有登录打印原因和第 4.4 节一样中转过程中的输出同样会干扰连接建立。而且中转机上的 shell 脚本输出造成的失败更难排查因为报错信息的指向会更模糊。如果中转机不允许直连需要用ProxyCommand加手动转发的方式配置会复杂一些我更建议优先去申请开放ProxyJump这种标准方式长期维护成本低得多。5.3 容易写错的几处别名、路径、缩进与注释这些细节错误单看很蠢但高峰期配十几台机器时几乎必犯。缩进。~/.ssh/config用缩进来表示属于哪个 Host 段混用空格和 Tab 在某些 ssh 实现里会被解析成不同的结果。统一用四个空格不要用 Tab。注释。行首#是注释。但注意别在配置行中间加注释有些实现会把后面的内容当成行内注释处理有些不会行为不统一。Windows 路径。IdentityFile C:\Users\你的用户名\.ssh\id_ed25519里的反斜杠在某些情况下会被当转义符用正斜杠更保险C:/Users/你的用户名/.ssh/id_ed25519。别名冲突。Host别名如果和某个真实域名重名ssh 会把它的配置应用到那个域名上导致一些莫名其妙的认证失败。别名统一加个前缀比如dev-、prod-能避免这类问题。通配段。有些配置模板会在文件开头写Host *来设置全局参数。要注意Host *段里的IdentityFile会应用到所有连接如果你想用IdentitiesOnly yes限制密钥就得在具体的 Host 段里覆盖。这两个一起出现的时候行为往往和直觉相反建议写完之后拿ssh -v 别名看一遍实际的密钥加载顺序。5.4 多环境并存时的组织方式手里环境多了之后建议按用途分组并在文件开头用注释标清楚# 生产环境 Host prod-web HostName 198.51.100.7 User deploy IdentityFile ~/.ssh/id_ed25519_prod # 测试环境 Host test-web HostName 198.51.100.30 User deploy IdentityFile ~/.ssh/id_ed25519_test给生产环境和测试环境用不同的密钥不只是安全习惯也是排查时的便利一旦出现认证失败密钥路径一眼就能看出连的是哪套环境不会出现以为在连测试结果改了生产这种事。如果团队协作还可以把这一份 config 放进版本管理路径用环境变量替代这样换机器时直接拉下来就能用。要注意私钥本身不要入库只放配置。6. 看起来像连接失败、其实不是的几类问题6.1 此扩展在此工作区中被禁用到底是什么含义这句话的完整版本通常是此扩展在此工作区中被禁用因为其被定义为在远程扩展主机中运行。第一次看到很容易理解成远程连接受限了或者扩展装不上其实它表达的是一个完全正常的设计有些扩展需要跑在远端比如语言服务、调试器、代码检查工具它们依赖远端的环境而另一些扩展只能跑在本地比如某些主题、本地文件操作工具。当你连上远程后VS Code 会按这个划分把扩展分别装到两边落在错误一侧的界面就会给你这么一句提示。所以看到它的时候先确认几件事扩展本身是否真的支持远程开发它应该装在哪一侧当前是不是连在远程窗口里。大部分情况下正确做法是在扩展面板里点在 SSH: 主机名 中安装或者干脆点在远程中重新安装。真正需要警惕的是另一种情况扩展在远端安装失败因为远端无法访问扩展市场或者磁盘空间不足。这时候界面可能也会给出类似的提示需要去看远端的扩展目录确认是否装上了。6.2 一直卡在正在打开远程或落入重连循环界面停在正在打开远程、Setting up SSH Host这类状态然后过一阵自己断开重连反复循环。这类现象的原因分布很广但有一个共同的排查起点看远端组件目录和远端日志。先确认连接到底走到哪一步了。如果~/.vscode-server/bin/commit-id/目录已经存在且非空说明组件下载这一关过了问题在启动如果目录根本不存在或者只有半截文件说明下载失败。远端日志的位置在~/.vscode-server/data/logs/下面按时间戳分目录。里面的remoteagent.log记录服务端启动过程能看到很具体的失败原因比如缺少某个动态库、端口被占用、权限不足。内存也是一个容易被忽略的因素。远端组件会在后台跑一个 node 进程如果目标机器内存很小比如 1GB 的入门云主机同时还跑着别的服务启动过程中被系统 kill 掉表现就是反复重连。这种情况可以先用dmesg | tail看有没有 OOM 记录。6.3 网络抖动导致的断线保活参数怎么设长时间开着远程窗口中间隔几分钟不动回来发现连接断了或者编辑器的状态需要重新加载。这通常是连接空闲后被中间的网络设备回收掉了。客户端侧的保活参数写进 config 就行Host * ServerAliveInterval 30 ServerAliveCountMax 6 TCPKeepAlive yesServerAliveInterval 30表示每 30 秒向服务端发一次心跳ServerAliveCountMax 6表示连续 6 次没回应才判定断开相当于给了 3 分钟的容忍窗口。这两个值配合起来对付一般的企业网络空闲回收足够了。服务端侧也可以配合设置/etc/ssh/sshd_config里的ClientAliveInterval和ClientAliveCountMax逻辑对称。两边都设的话取更宽松的一边生效。一个经验如果断线总是发生在某个固定时长之后比如整 5 分钟、整 10 分钟基本可以确定是中间设备有定时清理策略而不是 ssh 本身的超时。这种情况下调大保活间隔往往能解决。6.4 连上之后的 Python、C/C 环境配置连接通了只是开始接下来大概率会遇到远端解释器找不到或者C/C 智能提示报一堆红。Python 的情况VS Code 默认可能选中了系统的python3而你的项目在一个虚拟环境或者 conda 环境里。在命令面板执行Python: Select Interpreter选中远端那个正确的解释器路径。如果列表里压根没有你想要的环境多半是环境不在默认搜索路径里可以手动输入路径。远程开发时虚拟环境一定要在远端创建不要用本地路径映射否则会出现解释器存在但依赖装不上的情况。C/C 的情况智能提示依赖c_cpp_properties.json里的includePath。远端环境下这个文件要放在远端的工作区里路径也必须是远端的路径。一个常见错误是照抄了本地配置里的相对路径在远端根本解析不到。还有一个更隐蔽的坑如果项目依赖某个版本的工具链而远端装了多个版本compilerPath指向哪个直接决定了提示的结果。建议把它写成绝对路径避免 PATH 顺序变化导致行为漂移。6.5 端口转发、中文路径与几个边角问题端口转发。远端跑了个 Web 服务想在本机浏览器看VS Code 的端口面板可以自动检测并转发也可以手动添加。如果自动检测不生效比如服务绑在127.0.0.1而不是0.0.0.0手动加一条转发即可。要注意的是转发是基于 ssh 通道的所以原本的端口安全策略不会因此放开这是它的优点。中文路径与编码。远端文件名带中文时终端里可能出现乱码需要确认远端的 locale 设置locale命令必要时把LANG设成带 UTF-8 的形式。文件监视数量。大项目下可能会出现ENOSPC: System limit for number of file watchers reached这是服务端内核参数fs.inotify.max_user_watches达到上限。调大它需要管理员权限属于一次性配置。ssh 命令在断开后是否继续执行。这个和远程开发关系不大但问的人很多如果直接在终端里跑ssh 主机 长任务然后本地网络断了或者你按了 CtrlC远端那条命令通常会收到挂断信号而终止。想让它在远端继续跑标准做法是用nohup加输出重定向或者用tmux、screen这类会话工具跑在里面。我自己的习惯是重要任务一律进tmux这样断线重连后tmux attach就能看到进度比在日志里翻要舒服得多。7. 我自己的排查顺序和几条压箱底经验真到了手忙脚乱的时候人容易乱试。我给自己定了一套固定顺序基本能覆盖九成情况写在这里供参考。第一步看输出面板的Remote - SSH日志先判断故障在哪一段。第二步在系统终端裸跑ssh -vvv确认是不是 VS Code 特有的问题。第三步如果是认证问题检查服务端authorized_keys和三个权限位。第四步如果是连接很久之后才失败去远端看~/.vscode-server/data/logs/里的日志同时df -h和free -h各看一眼。第五步前四步都没结论删掉~/.vscode-server重来一次。第一条经验是关于改服务端配置的每次改/etc/ssh/sshd_config之前先另外开一个已经登录的终端窗口别关。改完先跑sshd -t校验语法再重启。如果新配置有问题你在那个保底窗口里还能改回来。我见过不止一次有人把ListenAddress或PermitRootLogin改错重启之后自己彻底进不去只能走控制台。第二条是关于猜的不要在同一个问题上同时改三处。一次性改了 config、换了密钥、又清了 known_hosts最后成功了也不知道是哪一步起了作用下次遇到同样问题还是抓瞎。一次只改一个变量改完立刻验证。第三条是关于 Windows 的先确认Get-Command ssh输出的是哪一个路径。这一条能省掉大量配置明明是好的的困惑。确认之后把私钥、config、known_hosts 都按那个路径对应的目录来组织不要一半在系统目录一半在 Git 目录。第四条是关于时间成本的如果一台机器的远程开发环境折腾超过半小时还没通就该考虑换容器化方案了。在目标机器上跑一个干净的开发容器把 ssh 端口映射出来VS Code 连容器。这么做隔离掉的是宿主机上所有历史遗留的环境问题——旧 glibc、奇怪的安全策略、被改乱的 shell 脚本一次性全部绕开。我现在给团队配新环境基本都走这条路省下来的排查时间远比配置容器花的时间多。
返回列表