使用 VS Code Remote Tunnel 进行远程开发

背景

传统 VS Code Remote-SSH 的连接方式依赖本地到服务器的 SSH 长连接:

在跨地区网络、校园网、NAT 或代理环境下,SSH 连接可能出现以下问题:

  • 长时间不操作后自动断开。
  • 网络延迟较高时,终端输入和输出体验变差。
  • 服务器没有公网 IP 或入站端口不方便开放。
  • 本地网络切换后,SSH 连接容易中断。

VS Code Remote Tunnel 提供了另一种远程开发方式。它在服务器端运行 code tunnel,由服务器主动建立出站连接;本地 VS Code 再通过 Tunnel 连接服务器。

这种方式不需要服务器开放公网入站端口,也不依赖传统 SSH 长连接,更适合高延迟或不稳定网络环境下的远程开发。

基准环境

本文基于以下环境:

1
2
3
4
服务器系统:Ubuntu 24.04
服务器架构:x86_64 / amd64
远程主机名:lab-server
VS Code 客户端:本地 VS Code Desktop

服务器上的 VS Code CLI 安装路径:

1
~/apps/vscode-cli/code

软链接路径:

1
~/.local/bin/code

安装 VS Code CLI

在 Ubuntu 24.04 服务器上执行:

 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
mkdir -p ~/apps/vscode-cli ~/.local/bin
cd ~/apps/vscode-cli

curl -sL "https://code.visualstudio.com/sha/download?build=stable&os=cli-linux-x64" -o vscode_cli.tar.gz
tar -xzf vscode_cli.tar.gz

ln -sf "$HOME/apps/vscode-cli/code" "$HOME/.local/bin/code"

export PATH="$HOME/.local/bin:$PATH"

SHELL_NAME="$(basename "${SHELL:-}")"

case "$SHELL_NAME" in
  zsh)
    SHELL_RC="$HOME/.zshrc"
    ;;
  bash)
    SHELL_RC="$HOME/.bashrc"
    ;;
  *)
    SHELL_RC="$HOME/.profile"
    ;;
esac

PATH_LINE='export PATH="$HOME/.local/bin:$PATH"'

if [ -f "$SHELL_RC" ]; then
  grep -qxF "$PATH_LINE" "$SHELL_RC" || echo "$PATH_LINE" >> "$SHELL_RC"
else
  echo "$PATH_LINE" > "$SHELL_RC"
fi

code --version

如果能正常输出 VS Code CLI 版本,说明安装成功。

第一次启动 Remote Tunnel

第一次启动需要完成账号登录。服务器上执行:

1
code tunnel --accept-server-license-terms --name lab-server

终端会显示一个登录链接和验证码。使用浏览器打开链接,使用 GitHub 或 Microsoft 账号登录。

登录成功后,终端会显示类似下面的地址:

1
https://vscode.dev/tunnel/lab-server/...

此时说明 lab-server 已经可以通过 VS Code Remote Tunnel 访问。

测试完成后,可以按 Ctrl+C 停止前台进程。

安装为 systemd 用户服务

前台运行只适合临时测试。长期使用应该安装为 systemd user service。

执行:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
CODE="$HOME/apps/vscode-cli/code"

systemctl --user stop code-tunnel 2>/dev/null || true

"$CODE" tunnel service uninstall 2>/dev/null || true

systemctl --user daemon-reload

"$CODE" tunnel unregister 2>/dev/null || true

"$CODE" tunnel service install --accept-server-license-terms --name lab-server

systemctl --user daemon-reload
systemctl --user enable --now code-tunnel

systemctl --user status code-tunnel --no-pager

"$CODE" tunnel status

如果看到:

1
Active: active (running)

说明 Remote Tunnel 服务已经正常运行。

设置开机自启

为了让服务器重启后 Remote Tunnel 自动恢复,需要启用 linger:

1
2
3
sudo loginctl enable-linger "$USER"

loginctl show-user "$USER" | grep Linger

期望输出:

1
Linger=yes

这样即使用户没有手动 SSH 登录,code-tunnel.service 也可以在后台运行。

本地 VS Code 连接服务器

本地 VS Code Desktop 安装扩展:Remote - Tunnels,然后按 Ctrl/Cmd + Shift + P 打开 Command Palette 然后选择 Remote Tunnels: Connect to Tunnel。随后选择和服务器端相同的 GitHub 或 Microsoft 账号登录。之后选择 lab-server (服务端配置完成及客户端登录账号后会自动出现在列表中)。连接成功后,即可打开远程项目目录。此时 VS Code 的编辑器、文件浏览器、终端和扩展都运行在远程 Ubuntu 24.04 服务器环境中。

常用管理命令

查看服务状态:

1
systemctl --user status code-tunnel --no-pager

查看最近日志:

1
journalctl --user -u code-tunnel -n 100 --no-pager

实时查看日志:

1
journalctl --user -u code-tunnel -f

重启服务:

1
systemctl --user restart code-tunnel

停止服务:

1
systemctl --user stop code-tunnel

卸载服务:

1
2
"$HOME/apps/vscode-cli/code" tunnel service uninstall
systemctl --user daemon-reload

注销当前 Tunnel:

1
"$HOME/apps/vscode-cli/code" tunnel unregister

查看 Tunnel 状态:

1
"$HOME/apps/vscode-cli/code" tunnel status

常见问题

提示 unit 文件变化

如果看到:

1
2
Warning: The unit file, source configuration file or drop-ins of code-tunnel.service changed on disk.
Run 'systemctl --user daemon-reload' to reload units.

执行:

1
2
systemctl --user daemon-reload
systemctl --user restart code-tunnel

本地 VS Code 看不到 lab-server

先确认服务器服务是否运行:

1
systemctl --user status code-tunnel --no-pager

再确认 Tunnel 状态:

1
"$HOME/apps/vscode-cli/code" tunnel status

如果仍然无法看到,重新注册:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
CODE="$HOME/apps/vscode-cli/code"

systemctl --user stop code-tunnel 2>/dev/null || true

"$CODE" tunnel service uninstall 2>/dev/null || true
"$CODE" tunnel unregister 2>/dev/null || true

systemctl --user daemon-reload

"$CODE" tunnel service install --accept-server-license-terms --name lab-server

systemctl --user daemon-reload
systemctl --user enable --now code-tunnel

"$CODE" tunnel status

服务正常但重启后没有自动恢复

检查 linger:

1
loginctl show-user "$USER" | grep Linger

如果不是 Linger=yes,执行:

1
sudo loginctl enable-linger "$USER"

推荐使用方式

Remote Tunnel 负责远程开发连接,适合日常编辑、终端操作、运行脚本和调试代码。

长时间任务仍然建议放在 tmux 中运行:

1
tmux new -s work

重新连接:

1
tmux attach -t work

这样即使 VS Code 客户端断开,远程任务也可以继续运行。

完整安装命令

下面是一套从零开始的完整安装命令,适用于 Ubuntu 24.04 x86_64 服务器。

 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
set -e

SERVER_NAME="lab-server"
CODE_DIR="$HOME/apps/vscode-cli"
CODE_BIN="$CODE_DIR/code"

mkdir -p "$CODE_DIR" "$HOME/.local/bin"
cd "$CODE_DIR"

curl -sL "https://code.visualstudio.com/sha/download?build=stable&os=cli-linux-x64" -o vscode_cli.tar.gz
tar -xzf vscode_cli.tar.gz

ln -sf "$CODE_BIN" "$HOME/.local/bin/code"

# Make code available in the current script immediately
export PATH="$HOME/.local/bin:$PATH"

# Persist PATH for the user's current shell: bash / zsh / fallback profile
SHELL_NAME="$(basename "${SHELL:-}")"

case "$SHELL_NAME" in
  zsh)
    SHELL_RC="$HOME/.zshrc"
    ;;
  bash)
    SHELL_RC="$HOME/.bashrc"
    ;;
  *)
    SHELL_RC="$HOME/.profile"
    ;;
esac

PATH_LINE='export PATH="$HOME/.local/bin:$PATH"'

if [ -f "$SHELL_RC" ]; then
  grep -qxF "$PATH_LINE" "$SHELL_RC" || echo "$PATH_LINE" >> "$SHELL_RC"
else
  echo "$PATH_LINE" > "$SHELL_RC"
fi

echo "PATH updated in: $SHELL_RC"

"$CODE_BIN" --version

systemctl --user stop code-tunnel 2>/dev/null || true

"$CODE_BIN" tunnel service uninstall 2>/dev/null || true
"$CODE_BIN" tunnel unregister 2>/dev/null || true

systemctl --user daemon-reload

"$CODE_BIN" tunnel service install --accept-server-license-terms --name "$SERVER_NAME"

systemctl --user daemon-reload
systemctl --user enable --now code-tunnel

sudo loginctl enable-linger "$USER"

systemctl --user status code-tunnel --no-pager

"$CODE_BIN" tunnel status

本地 VS Code 连接:

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy