Sleepstars 的记录室

Sleepstars 的记录室

如何在 CentOS 7/Ubuntu 16 中使用新版本 VSCode Remote Plugin

本文参考了如下来源,另外加入了一些我的踩坑经历,希望可以给大家一些参考

https://github.com/microsoft/vscode/issues/246375https://blog.csdn.net/yakamoz423/article/details/147982768https://code.visualstudio.com/docs/supporting/FAQ#_can-i-run-vs-code-on-older-windows-versions

VSCode Remote Plugin 局限性

在社区的多轮拉扯下,最后一版兼容 Glib-2.27 的版本定格在了 VSCode-1.98 上,之后更新的版本均不再支持 CentOS 7/Ubuntu 16 等旧版系统。而公司/学校提供的 HPC 几乎不可能给你升级系统的机会。进入了 AI Agent 的时代,1.98 这个过老的版本实在是没法用了,各种插件都开始依赖新版本的 VSCode。升级迫在眉睫!

为了进行兼容,可以使用 patchelf ,来使用用户态的 glib-2.28,以支持

修改开始前准备

  1. 需要进行修改的老版本系统的机器(后称本机)

  2. 一台比较新,具有 sudo 权限,具有外网连接方法的机器。本次使用 Debian 13演示,其余版本自行修改安装命令(避免编译拉取失败)(后称编译机)

新建编译机用户

若不是使用 root 登录的用户,可以跳过本步骤

编译 sysroot 的时候不能使用 root 用户,否则会报错,因此首先新建一个用户

adduser builduser

接着给用户添加到 sudo 用户列表

usermod -aG sudo builduser

编译安装crosstool-NG

sudo apt-get install -y gcc g++ gperf bison flex texinfo help2man make libncurses5-dev python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip patch rsync meson ninja-build
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.26.0.tar.bz2
tar -xjf crosstool-ng-1.26.0.tar.bz2 && cd crosstool-ng-1.26.0
./configure && make && sudo make install

编译新版 sysroot

由于现在最新版本的 VSCode-server 要求使用 GLIBCXX_3.4.26, aka at least GCC 9.1.0,故和原文不同之处在于使用 gcc 10.5.0 的模板进行编译:

mkdir toolchain-dir && cd toolchain-dir
wget https://github.com/microsoft/vscode-linux-build-agent/raw/refs/heads/main/x86_64-gcc-10.5.0-glibc-2.28.config
mv x86_64-gcc-10.5.0-glibc-2.28.config .config

本机 上输入 uname -a ,查看本机内核版本,例如我的环境就是 3.10.0

ct-ng menuconfig

这个时候会弹出一菜单窗口,选择 Operating System 下的 Version of linux 为不高于本机系统内核版本的值(必须低于本机)

接着开始编译,大约耗时 20 分钟左右,取决于网速和 CPU 性能

ct-ng build

保存编译结果

你需要分别保存一个动态库 so.2 和一个文件夹。

./x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2
./x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib64

记录好输出的内容,保存到 本机 下的一个目录,例如:

./x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2 => /home/somename/sysroot/lib/ld-linux-x86-64.so.2
./x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib64 => /home/somename/sysroot/lib64

下载安装 patchelf

patchelf 的版本必须 > 0.17,本次使用 0.18

wget https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-x86_64.tar.gz
tar -zxf patchelf-0.18.0-x86_64.tar.gz -C /home/somename/patchelf

设置启动脚本

按官方和社区的说法,这个时候应该添加到 ~/.bashrc 以让流程自动生效。但是根据 GitHub issue,这个方法最近不会生效,疑似是因为启动脚本的安全检查导致的。

如果直接绕过启动脚本运行 ./code-server,VSCode 会读取环境变量中的 patchelf 以及其他 glibc 相关变量,并自动使用 patchelf 进行修补。因此,仅执行一次 ./code-server --version 即可完成此修改,之后即可正常使用 VSCode Remote 进行连接。

为了实现该目标,我编写了一个 Bash 脚本并将其写入 ~/.ssh/rc。该脚本在每次 SSH 连接时自动对所有版本的 code‑server 执行 ./code-server --version,从而在版本更新时便于 patchelf 自动进行修改。相较于之前的做法,此方案的缺点在于首次使用新版本的 VSCode 登录时必然会失败,需要进行第二次(或多次,具体次数取决于 patchelf 的执行时间,可在第二次登录后适当等待后再尝试)登录才能正常进入。此后,同一版本的后续登录将不再出现等待情况。

脚本内容如下:

# ~/.ssh/rc
#!/bin/sh
# 不向 stdout/stderr 打印,防止破坏 VS Code 握手
exec >/dev/null 2>&1

# 你的 patchelf/兼容 glibc 路径
: "${VSCODE_SERVER_CUSTOM_GLIBC_LINKER:=/home/somename/sysroot/lib/ld-linux-x86-64.so.2}"
: "${VSCODE_SERVER_CUSTOM_GLIBC_PATH:=/home/somename/sysroot/lib64}"
: "${VSCODE_SERVER_PATCHELF_PATH:=/home/somename/patchelf/bin/patchelf}"

LOG="$HOME/.vscode-server/code-server-versions.log"
mkdir -p "$HOME/.vscode-server"

# 选择 login shell
if command -v bash >/dev/null 2>&1; then
  LOGIN_SHELL="bash"
  LOGIN_FLAG="-lc"
else
  LOGIN_SHELL="sh"
  LOGIN_FLAG="-lc"  # 大多数 /bin/sh 也接受 -lc;不行的话改成 -c
fi

for dir in "$HOME"/.vscode-server/bin/*; do
  [ -d "$dir" ] || continue

  # 1) 先触发自举(可能会 patchelf)
  if [ -x "$dir/server.sh" ]; then
    env \
      VSCODE_SERVER_CUSTOM_GLIBC_LINKER="$VSCODE_SERVER_CUSTOM_GLIBC_LINKER" \
      VSCODE_SERVER_CUSTOM_GLIBC_PATH="$VSCODE_SERVER_CUSTOM_GLIBC_PATH" \
      VSCODE_SERVER_PATCHELF_PATH="$VSCODE_SERVER_PATCHELF_PATH" \
      "$dir/server.sh" >/dev/null 2>&1 || true
  fi

  # 2) 再读取版本
  BIN="$dir/bin/code-server"
  [ -x "$BIN" ] || continue

  # 用 login shell 执行,同时再次内联传入变量,避免下游丢失
  env \
    VSCODE_SERVER_CUSTOM_GLIBC_LINKER="$VSCODE_SERVER_CUSTOM_GLIBC_LINKER" \
    VSCODE_SERVER_CUSTOM_GLIBC_PATH="$VSCODE_SERVER_CUSTOM_GLIBC_PATH" \
    VSCODE_SERVER_PATCHELF_PATH="$VSCODE_SERVER_PATCHELF_PATH" \
    "$LOGIN_SHELL" $LOGIN_FLAG "\"$BIN\" --version" >>"$LOG" 2>&1 || {
      printf '[%s] %s --version failed\n' "$(date +'%F %T')" "$BIN" >>"$LOG" 2>&1
    }
done

exit 0

需要注意提前按照你的安装目录修改 glibc 和 patchelf 的路径。

接着把脚本内容写入到 /.ssh/rc ,然后修改脚本执行权限

chmod 700 ~/.ssh/rc

接下来就可以尝试使用 SSH 客户端或者 VSCode 进行登录。

每次登录后,都会把相关脚本输出日志输出到 ~/.vscode-server/code-server-versions.log 中,如果成功修改应该会有如下的日志输出:

[2025-09-24 19:26:05] /example/.vscode-server/bin/258e40fedc6cb8edf399a463ce3a9d32e7e1f6f3/bin/code-server --version failed
Patching glibc from /example/test/compatible/so/lib64 with /example/test/compatible/patchelf/bin/patchelf...
Patching linker from /example/test/compatible/so/lib/ld-linux-x86-64.so.2 with /example/test/compatible/patchelf/bin/patchelf...
Patching complete.
1.104.1
0f0d87fa9e96c856c5212fc86db137ac0d783365
x64
Patching glibc from /example/test/compatible/so/lib64 with /example/test/compatible/patchelf/bin/patchelf...
Patching linker from /example/test/compatible/so/lib/ld-linux-x86-64.so.2 with /example/test/compatible/patchelf/bin/patchelf...
Patching complete.
/example/.vscode-server/bin/258e40fedc6cb8edf399a463ce3a9d32e7e1f6f3/bin/code-server: line 22: 38279 Segmentation fault      (core dumped) "$ROOT/node" ${INSPECT:-} "$ROOT/out/server-main.js" "$@"
[2025-09-24 19:27:41] /example/.vscode-server/bin/258e40fedc6cb8edf399a463ce3a9d32e7e1f6f3/bin/code-server --version failed
Patching glibc from /example/test/compatible/so/lib64 with /example/test/compatible/patchelf/bin/patchelf...
Patching linker from /example/test/compatible/so/lib/ld-linux-x86-64.so.2 with /example/test/compatible/patchelf/bin/patchelf...
Patching complete.
1.103.2
6f17636121051a53c88d3e605c491d22af2ba755
x64

如果注入失败,会有如下日志,检查相关变量路径是否正确:

[2025-09-24 19:09:02] /example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/bin/code-server --version
example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node)
example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node)
example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node: /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node)
example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node)
example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node: /lib64/libc.so.6: version `GLIBC_2.27' not found (required by example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node)
example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node)
example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by example/.vscode-server/bin/6f17636121051a53c88d3e605c491d22af2ba755/node)