云计算百科
云计算领域专业知识百科平台

无外网 Linux 服务器离线安装 VS Code Remote-SSH 指南(新版双包机制 + commit 一致)

点一下"转到定义",等三秒。打开个文件,状态栏转圈半分钟。想用 clangd 让跳转又快又准,结果它压根启动不了——因为你的 VS Code 在 Windows 上跑,代码却在网络盘的另一头。

这是我接手一台无外网 Linux 编译服务器时遇到的真实情况。解决办法大家都说得上来:上 Remote-SSH。可真到装的时候,网上一堆教程照着做,连不上。卡在 "Setting up SSH Host…" 转半天,最后报个错让你怀疑人生。

折腾一圈才发现,新版 VS Code 离线安装要下两个包,不是一个。网上老教程只讲一个,对新版根本无效。这篇文章就把这台离线服务器从"卡到不能用"到"clangd 秒跳"的完整过程拆开讲清楚,包括为什么这么做、踩了哪些坑、怎么排查。

你的代码跳转为什么慢到怀疑人生

先看问题出在哪。我们这台 Linux 编译服务器没外网,但 Windows 和它之间通过 SMB 把 Linux 的一个目录映射成了 F 盘。于是 VS Code 直接打开 F 盘里的工程,看起来跟本地一样。

网络盘 vs Remote-SSH 架构对比图

问题在于,VS Code 的 C/C++ 扩展是作为 Windows 进程在跑的。它要读的那几千个源文件、头文件,全在 F 盘后面那台 Linux 上。每一次文件读取,都是一次跨网络的 IO。

老的 Tag Parser 方案更惨。它要扫描工程里所有文件建符号索引,几千个文件一个个读,每个都走网络。你点个跳转,它在后台疯狂读网络盘,延迟就这么累积起来的。

clangd 呢,更直接。它根本跑不起来。clangd 是个 Linux 二进制,需要 Linux 路径、Linux 工具链。你在 Windows 端装 clangd 扩展,它找不到对应的二进制,或者拿到了也跑不了。

这里有个判断基线,我后面会反复强调:做代码索引的程序,必须和被索引的文件在同一台机器上。跨网络盘做索引,注定慢,注定别扭。

Remote-SSH 的本质:把索引进程搬过去

理解了上面这点,Remote-SSH 的解法就很自然:把索引进程搬过去,代码不用动。

Remote-SSH 不是远程桌面那种"把整个界面投过来"。它把活儿拆开:UI 留在你的 Windows 上(你熟悉的快捷键和插件都在),真正干活的进程跑在 Linux 服务器上。这个干活的进程叫 vscode-server。

连上之后,clangd 扩展装在远端,作为 Linux 进程跑,直接读本地磁盘上的源文件、compile_commands.json、头文件,零网络 IO。你点跳转,clangd 在本地几毫秒就响应了,结果传回 Windows 端渲染。

为什么这比 Tag Parser 强?Tag Parser 是全盘正则扫描,扫一遍建个静态索引,慢且不准(宏、条件编译搞不定)。clangd 基于 compile_commands.json,每个文件用真实的编译参数去解析,宏展开、头文件路径都是准的。一个是从目录里翻,一个是照着编译命令精确读,根本不是一个量级。

所以 Remote-SSH 不是打补丁,它从根上纠正了"索引进程和文件分离"这个错误架构。

离线安装最大的坑:新版要两个包

到装的时候了。有外网的话啥都好说,VS Code 首次连接会自动下载 server。可我们这台没外网,自动下载必失败,卡在 "Setting up SSH Host…" 直到超时。

离线安装的思路是:在 Windows 下载好包,传到 Linux,手动解压到位。但新版 VS Code(1.102+)需要两个包,缺一不可。这是整件事最容易踩的坑。

新版双包连接流程图

两个包分别是:

  • server 包 vscode-server-linux-x64.tar.gz,解压到 ~/.vscode-server/cli/servers/Stable-<commit>/server/,里面是 server 本体(node + out/ + 扩展)。
  • CLI 包 vscode-cli-linux-x64.tar.gz,解压成 ~/.vscode-server/code-<commit>,是连接入口二进制。

为什么是两个?新版把连接管理和语言服务解耦了。ssh 进来先执行的是 CLI 入口(code-<commit>),CLI 再去拉起 server(cli/servers/Stable-<commit>/server/bin/code-server)。CLI 管连接,server 管干活。

这里还有个路径演进的坑。旧版 VS Code(大约 1.86 之前)server 装在 ~/.vscode-server/bin/<commit>/,新版改到了 ~/.vscode-server/cli/servers/Stable-<commit>/server/。网上很多老教程写的是 bin/<commit>/,对新版完全无效。判断你装的是新版还是旧版路径:看 ~/.vscode-server/ 下有没有 code-<commit> 这个文件,有就是新版路径。

只装 server 不装 CLI 会怎样?ssh 进来找不到 code-<commit> 入口,VS Code 尝试自动下载 CLI,但没外网,连接失败。我就这么卡过,对比一位同事的 ps -ef | grep vscode-server 进程才发现,人家有 code-<commit> 入口而我没有。

commit 号:不是版本号,且必须三处一致

下载那两个包,要用到 commit 号。注意,commit 号不是版本号。

版本号是 1.102.1 这种,commit 号是一串 40 位十六进制 hash,在 VS Code 的 Help → About 里能看到,类似 7adae6a56e34cb64d08899664b814cf620465925。下载地址是拿 commit 号拼的:

https://update.code.visualstudio.com/commit:<commit号>/server-linux-x64/stable
https://update.code.visualstudio.com/commit:<commit号>/cli-linux-x64/stable

关键是,三处 commit 必须完全一致:Windows 客户端的 commit、server 包的 commit、CLI 包的 commit。差一个字符,VS Code 都认为你没装,重新触发下载,离线环境下就是连不上。

这意味着每次 VS Code 升级,commit 号会变,两个包都要重新下载对应版本。这是离线维护的持续成本,躲不掉。所以装之前一定先查准 commit,别下错版本白忙活。

完整安装十步走

理清原理后,操作其实不复杂,十步:

  • Windows 装 Remote-SSH 扩展(ms-vscode-remote.remote-ssh)
  • Help → About 查 commit 号(40 位)
  • 浏览器下两个包,分别重命名为 vscode-server-linux-x64.tar.gz 和 vscode-cli-linux-x64.tar.gz
  • 通过 F 盘(或任何内网传输)把两个包传到 Linux
  • Linux 解压两个包到位:server 到 cli/servers/Stable-<commit>/server/,CLI 到 ~/.vscode-server/code-<commit>
  • 配 SSH config 并连接
  • 装 clangd 扩展到远端
  • 验证代码跳转
  • 多工程共存
  • 编译之外的代码怎么看
  • 第 5 步是重点。解压用两个脚本:setup_vscode_server.sh <commit号> 把 server 包解压到新版路径,验证 node、bin/code-server、out/server-main.js 齐全;setup_vscode_cli.sh 把 CLI 包解压出 code 二进制,复制成 ~/.vscode-server/code-<commit>。

    两个脚本跑完,再跑自检 check_vscode_server.sh,8 项全 [OK] 才能去连:server 的 node、server-main.js、CLI 入口、clangd、.clangd、settings.json、compile_commands.json、SSH 服务。哪项 FAIL 脚本会直接给修复命令。

    SSH key 免密的四个坑

    配 SSH 连接本身不难,但免密登录这里坑特别多,一个个说。

    坑一:VS Code 走 ssh.exe 是非交互的。 你用 SecureCRT 连服务器,没配 key 它会弹窗问你密码。VS Code Remote-SSH 调的是 Windows 自带的 ssh.exe,非交互模式,没配 key 直接 Permission denied,不会弹窗。所以你以为"密码能连啊",到 VS Code 这就连不上。

    SSH key 免密配置流程图

    坑二:配了 key 还得加两行配置。 生成密钥 ssh-keygen -t ed25519,把公钥传到服务器的 ~/.ssh/authorized_keys,这都好理解。但光这样不够,VS Code 还会要密码。得在 SSH config 里加:

    Host nordic-server
    HostName <服务器IP>
    User <你的用户名>
    Port 22
    IdentityFile C:\\Users\\<你的用户名>\\.ssh\\id_ed25519
    IdentitiesOnly yes

    IdentitiesOnly yes 强制只用你指定的这个 key,避免 ssh-agent 里的其他 key 干扰。VS Code 走 ssh.exe 非交互,没这两行会回退到要密码。

    坑三:key 认证对权限敏感到变态。 服务器端 ~/.ssh 必须 700、authorized_keys 必须 600、home 目录不能让 group/other 可写。权限不对,SSH 会静默拒绝你的 key,直接回退到密码认证,你看着像"key 没生效",其实是权限问题。

    坑四:验证免密必须用 config 别名。 这是最隐蔽的坑。你想测免密通没通,习惯性敲 ssh <你的用户名>@<服务器IP>,发现不问密码,以为成功了。但 VS Code 还是连不上。

    原因是直连 IP 时,ssh-agent 可能记住了你私钥的 passphrase,帮你免密了。但 VS Code 走的是 config 别名 + IdentitiesOnly,不走 agent,passphrase 问题就暴露了。只有 ssh nordic-server(用别名)不问任何东西,才算真免密。如果别名还问 passphrase,去掉它:

    ssh-keygen -p -f $env:USERPROFILE\\.ssh\\id_ed25519

    输旧 passphrase,新 passphrase 两次回车留空。

    clangd 装远端,别装本地

    连上 SSH 后,装 clangd 扩展。这里容易错——clangd 必须装在 SSH 远端,不是本地。

    VS Code 的扩展面板分两栏:LOCAL(本地 Windows)和 SSH: nordic-server(远端 Linux)。在 clangd 扩展卡片上要点 "Install in SSH: nordic-server"。如果只装到 LOCAL,clangd 作为 Windows 进程跑,又回到网络盘问题了。

    clangd 基于 compile_commands 工作机制图

    clangd 精确跳转的基石是 compile_commands.json。这个文件记录了每个源文件真实的编译参数,包含路径、宏定义全在里面。clangd 拿到它,每个文件都按真实编译命令解析,宏和头文件路径都是准的。没有它,clangd 只能 fallback 用默认参数猜,简单符号能跳,复杂的一跳一个不准。

    这里还有个版本坑。我在 settings.json 的 clangd.arguments 里配了 –cache-dir=…,结果 clangd 启动直接退出,Output 里报 Server process exited with code 1。折腾半天才发现,clangd 18 根本没有 –cache-dir 这个参数(–background-index-cache-dir 也没有)。手动跑 /usr/bin/clangd <参数> –check=xxx.c,stderr 会打印 Unknown command line argument '–cache-dir=…'。删掉就好了,–background-index 自带索引持久化,clangd 自己管存储位置。

    教训:clangd 不同版本支持的参数不一样,配 clangd.arguments 前用 clangd –help 确认参数存在。远端装的 clangd 扩展版本(比如 0.6.0)倒不影响跳转能力,它只是个前端,真正干活的是 /usr/bin/clangd 那个二进制。

    如果远端装 clangd 扩展也因网络失败,走 VSIX 离线:Windows 浏览器从扩展市场下载 .vsix,传到 Linux,VS Code 里 Install from VSIX。

    连不上?按这五层逐层排查

    装完连不上,别盲目重试。按这个顺序逐层定位,每层通了再查下一层:

    第 1 层 网络层:Windows PowerShell 跑 ssh <你的用户名>@<服务器IP> "echo OK"。打印 OK 就通,进下一层。超时是网络/防火墙,拒绝是 SSH 服务没开。

    第 2 层 SSH 认证层:跑 ssh nordic-server "echo OK"(用别名)。打印 OK 进下一层;Permission denied 是认证问题,回去查 key;Could not resolve hostname 是 config 没配对。注意区分:ssh user@IP 能连但 ssh nordic-server 不行是 config 问题,两个都不行是认证/网络问题。

    第 3 层 server 安装层:Linux 端跑 check_vscode_server.sh,应全 [OK]。最常见 FAIL 是 CLI 入口那项,说明没装 CLI 包。手动验证 server 能否启动:~/.vscode-server/cli/servers/Stable-$COMMIT/server/node ~/.vscode-server/cli/servers/Stable-$COMMIT/server/out/server-main.js –version,打印版本号就正常。再确认三处 commit 完全一致。

    第 4 层 VS Code 状态层:前三层都通还连不上,通常是 VS Code 缓存了失败状态。F1 → Remote-SSH: Kill VS Code Server on Host,再 Developer: Reload Window,重新连。远端可清残留:pkill -f vscode-server、清 logs 和 lock 文件,但别删 cli/servers/ 和 code-<commit>,那是安装包。

    第 5 层 clangd 层:连上了但跳转不对,看这层。打开 .c 文件,View → Output 选 clangd 通道,看日志。clangd version 18.1.3 + Loaded compilation database from … 就是正常的。

    有个实战定位手段很管用:如果同事用同版本 VS Code 在同台服务器连上了,对比他的 ~/.vscode-server/ 路径结构,ps -ef | grep vscode-server 看他的进程命令行,照抄路径。我这次排查就是靠对比同事进程发现新版路径变了、需要 CLI 包的。

    编译之外的代码怎么看

    clangd 有个局限得说清楚:只有编译进镜像的文件才有精确跳转。没在 compile_commands.json 里的文件,clangd 没有编译参数,跳转会失败或不准。

    哪些算"编译之外"?prj.conf 里 CONFIG_XXX=n 的源文件、其他工程的代码、SDK 里没选用的驱动、samples 和 tests 目录。这些 clangd 都管不了。

    对策按推荐顺序:第一,用 CodeGraph(如果有的话),它索引整个工作区所有符号,不依赖 compile_commands,没编译的代码也能查,几秒出结果,补上 clangd 的短板。第二,VS Code 全局文本搜索 Ctrl+Shift+F 兜底,不精确(同名混),但能定位文件再人工判断。第三,把要看的文件纳入编译——Zephyr/NCS 在 prj.conf 开 CONFIG_XXX=y 重新 build,CMake 在 CMakeLists 加源文件重新 cmake,一劳永逸。第四,少数文件用 compile_flags.txt,每行一个参数放文件所在目录。第五,clangd fallback 模式自动启用但别指望它准。

    日常跳转用 clangd,编译内的秒跳。跨工程或编译外的代码,用 CodeGraph 或全局搜索。长期要看的模块,开配置重新 build 纳入 clangd。

    六条真实踩坑记录

    这次安装实际遇到的问题,供你排查时参考:

  • 只装 server 没装 CLI → 连接失败。根因:新版需要 cli-linux-x64 单独的包作 ssh 入口。定位:对比同事进程发现他有 code-<commit> 而我没有。

  • server 装在旧路径 bin/<commit>/ → VS Code 找不到。根因:新版路径改到 cli/servers/Stable-<commit>/server/。定位:看同事进程命令行里的路径照抄。

  • server 入口文件名变了 → 老脚本找 bin/code-server-oss 找不到。根因:新版叫 bin/code-server(无 -oss)。不影响 VS Code(它按 product.json 找),但自检脚本要适配。

  • SecureCRT 能连但 VS Code 不能 → 排除网络/认证,锁定 VS Code 自身。定位:PowerShell 跑 ssh <你的用户名>@<服务器IP> "echo OK" 直接打印 OK,说明 Windows 的 ssh.exe 没问题,问题在 server 安装层。

  • 本机自连报 Permission denied → 误判为认证问题。实际是本机没密码,不代表服务器拒绝你。教训:诊断命令要在客户端(Windows)跑,不是在服务器本机跑。

  • clangd Server process exited with code 1 → clangd 启动失败。根因:clangd.arguments 配了 –cache-dir,但 clangd 18 没这参数,启动直接退出。定位:手动跑 /usr/bin/clangd <参数> –check=xxx.c,stderr 打印 Unknown command line argument。解决:删掉 –cache-dir。

  • 升级维护

    VS Code 升级后 commit 号变,需重新走下载两包、解压的流程。旧 commit 目录可删:rm -rf ~/.vscode-server/cli/servers/Stable-<旧commit> 和 rm -f ~/.vscode-server/code-<旧commit>。

    改了 prj.conf 后跳转变不准?重新 build 生成新的 compile_commands.json,clangd 自动重载(.clangd 里配了 Index.Background: Build)。


    回到开头那个判断基线:索引进程必须和文件同机。Remote-SSH 就是把这条原则在离线环境里落地。离线环境下真正的难点是新版那两个包、commit 三处一致、SSH key 的四个坑。这些理清了,clangd 秒跳不难。

    你离线服务器上还在用网络盘硬扛代码跳转吗?或者装 Remote-SSH 卡在哪一步了?评论区说说,有用的话点个在看,让更多被网络盘折磨的工程师看到。


    标签:VS Code · Remote-SSH · 离线安装 · clangd · 嵌入式开发

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 无外网 Linux 服务器离线安装 VS Code Remote-SSH 指南(新版双包机制 + commit 一致)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!