Ubuntu 多用户并发远程桌面部署

本文提供一套面向 Ubuntu 的可复现部署方案,核心目标是实现“多用户并发远程桌面”:服务器重启后服务自动恢复,不同账户可同时接入并使用彼此隔离的 GNOME 会话,Windows 客户端可按账号与显示号稳定连接。

TurboVNC 与 VirtualGL 的作用

  • VNC(Virtual Network Computing):一种基于远程帧缓冲(RFB)的远程桌面协议,负责将服务器图形会话的画面编码后传输到客户端,并将客户端键盘/鼠标事件回传到服务器执行。
  • TurboVNC:远程桌面的“通道和会话管理器”,它负责把服务器桌面画面压缩后传到客户端,并为不同用户维护各自独立的会话。
  • VirtualGL:3D 图形的“加速桥接层”,当你在远程桌面里运行依赖 OpenGL 的程序时,它负责把 3D 渲染路径处理好,避免纯软件渲染导致的卡顿、黑屏或性能明显下降。

连接界面示意

TurboVNC 连接界面示意图

1. 目标

完成后你将获得:

  • Ubuntu 重启后 TurboVNC 自动启动(无需图形界面登录)
  • 同一台服务器可让多个 Linux 账户并行使用各自独立的远程桌面
  • 每个账户可创建多个 VNC 会话(不同显示号/端口),互不干扰
  • Windows 端可通过 VNC 客户端稳定连接到对应账户的 GNOME 桌面

2. 适用环境

  • Ubuntu 22.04
  • VNC 显示号::2
  • VNC 端口:5902
  • 安装方式:用户目录 rootless 安装(不写系统 /opt

3. 软件下载地址(官方)

4. 一次性部署步骤

4.1 创建目录并下载安装包

mkdir -p ~/.local/src ~/.local/opt/rootfs ~/.local/bin ~/.vnc ~/.config/systemd/user ~/.cache

curl -L 'https://sourceforge.net/projects/turbovnc/files/3.1/turbovnc_3.1_amd64.deb/download' -o ~/.local/src/turbovnc_3.1_amd64.deb
curl -L 'https://sourceforge.net/projects/virtualgl/files/3.1/virtualgl_3.1_amd64.deb/download' -o ~/.local/src/virtualgl_3.1_amd64.deb

4.2 解包到用户目录(rootless)

dpkg-deb -x ~/.local/src/turbovnc_3.1_amd64.deb ~/.local/opt/rootfs
dpkg-deb -x ~/.local/src/virtualgl_3.1_amd64.deb ~/.local/opt/rootfs

4.3 创建启动包装脚本

写入 ~/.local/bin/turbovnc-vncserver

cat > ~/.local/bin/turbovnc-vncserver <<'EOF1'
#!/usr/bin/env bash
set -euo pipefail
TVNC_HOME="$HOME/.local/opt/rootfs/opt/TurboVNC"
exec "$TVNC_HOME/bin/vncserver" "$@"
EOF1
chmod +x ~/.local/bin/turbovnc-vncserver

写入 ~/.local/bin/turbovnc-vncpasswd

cat > ~/.local/bin/turbovnc-vncpasswd <<'EOF1'
#!/usr/bin/env bash
set -euo pipefail
TVNC_HOME="$HOME/.local/opt/rootfs/opt/TurboVNC"
exec "$TVNC_HOME/bin/vncpasswd" "$@"
EOF1
chmod +x ~/.local/bin/turbovnc-vncpasswd

写入 ~/.local/bin/turbovnc-vncviewer

cat > ~/.local/bin/turbovnc-vncviewer <<'EOF1'
#!/usr/bin/env bash
set -euo pipefail
TVNC_HOME="$HOME/.local/opt/rootfs/opt/TurboVNC"
exec "$TVNC_HOME/bin/vncviewer" "$@"
EOF1
chmod +x ~/.local/bin/turbovnc-vncviewer

写入 ~/.local/bin/vglrun-local

cat > ~/.local/bin/vglrun-local <<'EOF1'
#!/usr/bin/env bash
set -euo pipefail
VGL_HOME="$HOME/.local/opt/rootfs/opt/VirtualGL"
VGL_LIB="$HOME/.local/opt/rootfs/usr/lib"
exec "$VGL_HOME/bin/vglrun" -ld "$VGL_LIB" "$@"
EOF1
chmod +x ~/.local/bin/vglrun-local

4.4 配置 VNC 内 GNOME 会话

写入 ~/.vnc/xstartup

cat > ~/.vnc/xstartup <<'EOF1'
#!/bin/sh
set -eu
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
unset DESKTOP_SESSION
unset GDMSESSION
unset XDG_SESSION_DESKTOP
export XDG_SESSION_TYPE=x11
export GNOME_SHELL_SESSION_MODE=ubuntu
exec dbus-launch --exit-with-session gnome-session --session=ubuntu
EOF1
chmod +x ~/.vnc/xstartup

4.5 设置 VNC 密码

turbovnc-vncpasswd

4.6 配置 systemd 用户服务(开机自启入口)

写入 ~/.config/systemd/user/turbovnc.service

cat > ~/.config/systemd/user/turbovnc.service <<'EOF1'
[Unit]
Description=TurboVNC Server Session (:2)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStartPre=/usr/bin/rm -f /tmp/.X2-lock /tmp/.X11-unix/X2
ExecStart=%h/.local/bin/turbovnc-vncserver :2 -fg -geometry 1920x1080 -depth 24 -xstartup %h/.vnc/xstartup -noautokill
ExecStop=%h/.local/bin/turbovnc-vncserver -kill :2
Restart=always
RestartSec=2

[Install]
WantedBy=default.target
EOF1

启用并启动:

systemctl --user daemon-reload
systemctl --user enable turbovnc.service
systemctl --user restart turbovnc.service

4.7 开启 linger(确保重启后无需登录也能启动)

先检查:

loginctl show-user "$USER" -p Linger

若输出不是 Linger=yes,执行(需要管理员权限):

sudo loginctl enable-linger "$USER"

4.8 增加 @reboot 兜底(可选)

创建兜底脚本:

cat > ~/.local/bin/turbovnc-autostart-ensure <<'EOF1'
#!/usr/bin/env bash
set -euo pipefail
LOG="$HOME/.cache/turbovnc-autostart.log"
mkdir -p "$HOME/.cache"
{
  echo "===== $(date '+%F %T') reboot ensure ====="
  if systemctl --user is-active --quiet turbovnc.service; then
    echo "turbovnc.service already active"
  else
    echo "starting turbovnc.service"
    systemctl --user start turbovnc.service || true
  fi
} >>"$LOG" 2>&1
EOF1
chmod +x ~/.local/bin/turbovnc-autostart-ensure

写入 crontab:

(crontab -l 2>/dev/null | grep -v 'turbovnc-autostart-ensure' ; \
 echo '@reboot /bin/bash -lc "sleep 25; $HOME/.local/bin/turbovnc-autostart-ensure"') | crontab -

5. 部署后验证

5.1 检查服务状态

systemctl --user is-enabled turbovnc.service
systemctl --user is-active turbovnc.service

期望输出:

  • enabled
  • active

5.2 检查端口监听

ss -ltnp | grep 5902

期望看到 0.0.0.0:5902Xvnc 监听。

5.3 重启后验证

sudo reboot

系统启动后(可不登录图形界面),从另一台设备连接:

  • <Ubuntu_IP>:5902

6. Windows 端连接步骤

6.1 安装客户端

推荐:TurboVNC Viewer(或 TigerVNC Viewer)。

6.2 填写连接地址

  • <Ubuntu_IP>:5902
  • <Ubuntu_IP>:2

6.3 登录

输入在 turbovnc-vncpasswd 中设置的密码。

7. 常用运维命令

# 查看状态
systemctl --user status turbovnc.service

# 重启服务
systemctl --user restart turbovnc.service

# 停止服务
systemctl --user stop turbovnc.service

# 手工启动/停止某显示号
~/.local/bin/turbovnc-vncserver :2 -geometry 1920x1080 -depth 24 -xstartup ~/.vnc/xstartup -noautokill
~/.local/bin/turbovnc-vncserver -kill :2

# 查看日志
journalctl --user -u turbovnc.service -n 200 --no-pager
tail -n 200 ~/.vnc/localhost:2.log

8. 常见问题

8.1 http://<Ubuntu_IP>:5902 打不开

5902 是 VNC(RFB)端口,不是 HTTP 网页端口。请使用 VNC 客户端,不要用浏览器。

8.2 Windows 连不上

按顺序排查:

  1. 查看服务状态:systemctl --user status turbovnc.service
  2. 查看端口监听:ss -ltnp | grep 5902
  3. 查看当前 IP:hostname -I
  4. 如启用防火墙,放行 5902/TCP

8.3 黑屏或卡住

systemctl --user restart turbovnc.service

重连一次。

8.4 与 GNOME Remote Desktop 冲突

若会话里存在 gnome-remote-desktop.service,可能与 TurboVNC 冲突。

排查:

  1. systemctl --user status gnome-remote-desktop.service
  2. ps -ef | rg -i "gnome-remote-desktop|vncserver|Xvnc" | rg -v rg
  3. ss -ltnp | rg "3389|5902"

修复:

  1. systemctl --user disable --now gnome-remote-desktop.service
  2. systemctl --user mask gnome-remote-desktop.service
  3. gsettings set org.gnome.desktop.remote-desktop.rdp enable false
  4. gsettings set org.gnome.desktop.remote-desktop.vnc enable false
  5. systemctl --user restart turbovnc.service

8.5 快捷键被本机拦截(如 Ctrl+Alt+T

这是 TurboVNC Viewer 的键盘抓取模式导致。可在连接参数中添加:

turbovnc-vncviewer -grabkeyboard always 127.0.0.1:2

或在 ~/.vnc/default.turbovnc 写入:

GrabKeyboard=Always

9. VirtualGL 使用提示(可选)

在 VNC 会话内运行 3D 程序:

vglrun-local <your-3d-app>

如需完整 GPU 授权策略(vglserver_config)与系统级优化,需要额外管理员权限配置。

10. 关键文件路径

  • ~/.config/systemd/user/turbovnc.service
  • ~/.vnc/xstartup
  • ~/.local/bin/turbovnc-vncserver
  • ~/.local/bin/turbovnc-vncpasswd
  • ~/.local/bin/turbovnc-vncviewer
  • ~/.local/bin/vglrun-local
  • ~/.local/bin/turbovnc-autostart-ensure