在旧版集群系统上运行远程 VS Code 的方案,借助容器绕过限制。

主要问题:如果本地 VS Code 版本高于 1.98,连接时可能出现“远程主机不符合 glibc 和 libstdc++ VS Code Server 先决条件”的报错。这与远程系统版本较旧有关。此前尝试过手动替换新版本组件,但稳定性不足,容易出现断联;而长期使用低版本 VS Code 又会影响新版插件的使用。

这里使用 Singularity 启动 VS Code Server。该方案基本解决了远程连接问题,但仍不适合直接在容器内提交计算任务脚本或查询任务状态。

方法:将 VS Code Server 自带的 node 可执行文件替换为一个 wrapper 脚本。VS Code 启动时先执行该 wrapper,再由 wrapper 进入 Singularity 容器,并调用容器环境中的实际 node 运行 VS Code Server。

连接方式:

1
srun --partition=cpu  --nodelist=cpu07 --cpus-per-task=1 --pty bash

进入节点后,可以在 Remote-SSH 中连接对应节点并启动容器环境。终端中如需使用 conda,可先初始化 shell 环境:

1
source ~/.bashrc

注意: Step 1 启用 node wrapper

  • remote.SSH.useExecServer = true 是 VS Code Remote-SSH 较新的启动方式。开启后,连接服务器时不再通过 node 启动,而是使用预编译的 Rust CLI 程序。该 CLI 会先检查系统版本;在 CentOS 7 环境中可能因 glibc 版本过旧而直接退出,并绕过前面配置的 node wrapper。
  • 按下快捷键 Cmd + , 打开设置。在上方搜索框输入:useExecServer
  • 找到 Remote.SSH: Use Exec Server 这个选项,取消选中

Step 2 对齐版本 本地的 VS Code 是 1.109.5 (对应的 commit 是 0725862...)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
COMMIT="072586267e68ece9a47aa43f8c108e0dcbf44622"
cd ~/.vscode-server/bin/$COMMIT

# 1. 删除此前下载失败或不完整的压缩包
rm -f vscode-server.tar.gz

# 2. 使用对应 commit 的 URL 重新下载
echo "正在下载 1.109.5 核心..."
curl -sL "https://update.code.visualstudio.com/commit:${COMMIT}/server-linux-x64/stable" -o vscode-server.tar.gz

# 3. 解压 VS Code Server
tar -zxf vscode-server.tar.gz --strip-components 1
rm vscode-server.tar.gz

# 4. 替换 node 为 Singularity wrapper
echo "正在写入 Singularity wrapper..."
mv node node_real

COMMIT="072586267e68ece9a47aa43f8c108e0dcbf44622"
cd ~/.vscode-server/bin/$COMMIT

cat << 'EOF' > node
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

export XDG_RUNTIME_DIR=$HOME/.vscode-server/run-tmp
mkdir -p $XDG_RUNTIME_DIR
chmod 700 $XDG_RUNTIME_DIR

# 使用环境变量减少 Singularity/Apptainer 输出
export SINGULARITY_SILENT=1
export APPTAINER_SILENT=1

# 避免使用部分旧版本 Singularity 不支持的 --quiet 参数
exec /software/singularity/bin/singularity exec \
--env XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
--bind $XDG_RUNTIME_DIR:/tmp \
--bind /etc/pki/tls/certs/ca-bundle.crt:/etc/ssl/certs/ca-certificates.crt \
~/software/ubuntu-dev.sif \
$DIR/node_real "$@"
EOF

echo "Singularity wrapper 已写入。"

解决代理网络问题。这里本地代理使用 V2RayN,因此端口设置为 10808

1
RemoteForward 10808 127.0.0.1:10808

在脚本中添加代理设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
COMMIT="072586267e68ece9a47aa43f8c108e0dcbf44622"
cd ~/.vscode-server/bin/$COMMIT

cat << 'EOF' > node
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

export XDG_RUNTIME_DIR=$HOME/.vscode-server/run-tmp
mkdir -p $XDG_RUNTIME_DIR
chmod 700 $XDG_RUNTIME_DIR

export SINGULARITY_SILENT=1
export APPTAINER_SILENT=1

# ========== 代理环境变量注入 ==========
# 指向通过 SSH RemoteForward 映射过来的本地端口
export http_proxy="http://127.0.0.1:10808"
export https_proxy="http://127.0.0.1:10808"
# 注意:必须排除本地回环地址,否则 VS Code 的底层 Socket 通信可能中断。
export no_proxy="localhost,127.0.0.1,::1,0.0.0.0"
# ==============================================

# exec 命令中使用 --env 将代理参数带入 Ubuntu 容器
exec /software/singularity/bin/singularity exec \
--env http_proxy=$http_proxy \
--env https_proxy=$https_proxy \
--env no_proxy=$no_proxy \
--env XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
--bind $XDG_RUNTIME_DIR:/tmp \
--bind /etc/pki/tls/certs/ca-bundle.crt:/etc/ssl/certs/ca-certificates.crt \
~/software/ubuntu-dev.sif \
$DIR/node_real "$@"
EOF

echo "代理环境变量已写入。"

此外,VS Code Remote-SSH 会尝试使用 wget 检查后端服务端口。集群 CentOS 7 节点上的 wget 版本较旧,不支持 --no-config 参数,可能导致检查过程报错退出。可以在本地 VS Code 客户端中修改设置进行适配:

  • Cmd + , (Command + 逗号) 打开设置
  • 搜索框输入:useCurlAndWgetConfigurationFiles
  • 找到 Remote.SSH: Use Curl And Wget Configuration Files,并将其选中。选中后,VS Code 不再向 wget 传递 --no-config 参数,更适合 CentOS 7 环境。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
COMMIT="072586267e68ece9a47aa43f8c108e0dcbf44622"
cd ~/.vscode-server/bin/$COMMIT

cat << 'EOF' > node
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

export XDG_RUNTIME_DIR=$HOME/.vscode-server/run-tmp
mkdir -p $XDG_RUNTIME_DIR
chmod 700 $XDG_RUNTIME_DIR

export SINGULARITY_SILENT=1
export APPTAINER_SILENT=1

# 注入反向代理(确保本地已配置 RemoteForward 10808 127.0.0.1:10808)
export http_proxy="http://127.0.0.1:10808"
export https_proxy="http://127.0.0.1:10808"
export no_proxy="localhost,127.0.0.1,::1,0.0.0.0"

# 将代理环境变量传给容器内部的真实 node
exec /software/singularity/bin/singularity exec \
--env http_proxy=$http_proxy \
--env https_proxy=$https_proxy \
--env no_proxy=$no_proxy \
--env XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
--bind $XDG_RUNTIME_DIR:/tmp \
--bind /etc/pki/tls/certs/ca-bundle.crt:/etc/ssl/certs/ca-certificates.crt \
~/software/ubuntu-dev.sif \
$DIR/node_real "$@"
EOF

echo "Node wrapper 已更新。"