上周为了一台 Ubuntu 工作站能远程办公,我连续折腾了两个晚上。最开始我天真地以为装个 TightVNC、开个端口就完事,结果第一个连接就给了我一记重锤:vncserver 启动成功,VNC Viewer 连上去却只有一片黑色和灰色背景,桌面环境影子都没见到。后面又陆续踩了 Xauthority 权限、锁屏冲突、GNOME 会话起不来等好几个坑,最后换到 x11vnc 才终于稳定下来。这篇文章就把这趟从 TightVNC 到 x11vnc 的完整踩坑过程写出来,包括每一步的根因、排错命令和最终可用配置,希望能帮你在远程桌面这件事上少浪费几个晚上。
1. 为什么我没选 RDP,也没直接用 x11vnc
很多人第一次配 Ubuntu 远程桌面时都会在 VNC 和 RDP 之间犹豫。我当时也纠结过一阵,先说说最终选择 VNC 这条路的原因。
RDP 协议在 Windows 上体验确实好,但 Linux 下面想用 RDP,往往要装 xrdp 这类服务端。xrdp 本身不算复杂,问题在于它和现代桌面会话的“挂接”经常出现奇奇怪怪的状况,尤其是 Ubuntu 新版本带 GNOME 的情况下,xrdp 拉起来的会话很容易变成一个孤立会话,看起来登录进去了,实际桌面组件没起来,或者操作特别卡。另一方面,VNC 的客户端生态非常成熟,Windows、macOS、手机上都有一堆现成的客户端,Server 端也有好几种实现,出了问题排错资料也相对好找。所以我最后还是把主力放在了 VNC 上。
但 VNC 内部也有很大区别。TightVNC 的定位是“创建一个虚拟显示器并在这个显示器上启动一套新的桌面”,本质上是另起炉灶;x11vnc 则是“直接读取当前物理显示器的画面并转发出去”,更像一个远程监控加控制的桥梁。按理说我没少看博客,应该一开始就选 x11vnc,但当时想着 TightVNC 是老牌方案、教程多,就想着先拿它试一把,结果这一试就试出了后面三个大坑。
后来回头看,这个选择本身没有绝对的对错,但一定要明白两者的模型差异。如果你需要的是“远程查看物理屏上正在跑的东西”,x11vnc 从一开始就是更合适的;如果你只是想要一个随时可用的独立桌面会话,TightVNC 反而有它的价值。很多教程默认把 VNC 当成一个整体来写,导致踩坑的人根本不知道问题出在“桌面启动”和“画面传输”是两件完全独立的事。
2. TightVNC 的第一层黑色滤镜:vncserver 启动了,客户端却只看得到背景壁纸
2.1 安装和启动其实很简单,问题全在后面
TightVNC 的安装过程非常顺手,基本就是两条命令的事:
sudo apt update sudo apt install tightvncserver安装之后先设置一个 VNC 访问密码:
vncpasswd这个密码会被保存在~/.vnc/passwd文件里,VNC 客户端连接时要用它登录,跟系统的登录密码没有关系,我一开始还傻傻地试了系统密码,结果一直认证失败。
接着启动虚拟显示器:
vncserver :1 -geometry 1440x900 -depth 24参数含义很直观,:1表示创建编号为 1 的显示,:0保留给物理屏幕,所以一般从 1 开始;-geometry是分辨率;-depth 24是色彩深度。启动成功后终端会显示类似New '你的主机名:1 (用户名)' desktop is :1的信息,看起来一切正常。
然后我打开 VNC Viewer,输入IP:1,心想这次总该见到桌面了。结果屏幕上只有两种颜色:大面积的黑,或者一块平平无奇的灰底,偶尔能看见鼠标光标在动,但就是没有任何窗口、任务栏或桌面图标。
2.2 黑屏的根因:VNC 服务端只负责“屏幕输出”,不负责“启动桌面”
这个问题最气人的地方在于,日志里没有明显报错,网上搜索出来的答案五花八门,有人说是显卡驱动问题,有人说是加密问题,甚至有人建议重装系统。其实绝大多数情况下,罪魁祸首就是~/.vnc/xstartup这个启动脚本没有配置好。
TightVNC 启动一个虚拟显示器后,这个显示器上默认是什么都不跑的,它不会自动启动 GNOME、XFCE 或者任何桌面环境。它只是一个空白的 X 显示,等待用户告诉它该启动什么。如果没有在xstartup里写清楚要启动的桌面命令,那客户端看到黑屏和灰底就再正常不过了。
VNC 服务端和桌面启动是两件事,这个认知是我这次踩坑最大的收获。你可以把 VNC 服务端理解成一台摄影机,它负责把你需要看的画面编码传走,但如果镜头前面什么都没有,再好的摄影机也只能拍出黑屏。xstartup就是那个“布置摄影棚”的脚本。
2.3 修复 xstartup 并让桌面真正跑起来
找到~/.vnc/xstartup,如果文件不存在就手动创建。我最后的配置是这样的:
#!/bin/bash export XAUTHORITY="$HOME/.Xauthority" xrdb $HOME/.Xresources 2>/dev/null || true dbus-launch --exit-with-session startxfce4 &注意两件事:第一,脚本要有执行权限;第二,我在这里选择了 XFCE 桌面而不是 GNOME,原因后面会说。给权限并重启服务:
chmod +x ~/.vnc/xstartup vncserver -kill :1 vncserver :1 -geometry 1440x900 -depth 24再连一次,桌面就正常出现了。
如果你执着于用系统原本的 GNOME 桌面环境,把最后一行替换成:
unset DBUS_SESSION_BUS_ADDRESS unset SESSION_MANAGER dbus-launch --exit-with-session gnome-session --session=ubuntu &但我不太推荐在 TightVNC 下面硬跑 GNOME,原因下面会展开。
2.4 养成看 VNC 日志的习惯
排查黑屏问题时最容易走弯路,是因为很多人不看日志。VNC server 的日志在~/.vnc/目录下,文件名类似你的主机名:1.log。每次启动失败或者桌面没起来,用下面命令看最后几十行:
tail -50 ~/.vnc/你的主机名:1.log常见的错误类型其实就那么几种:
| 症状 | 大概率原因 |
|---|---|
日志里提示command not found | xstartup 里的桌面启动命令不存在,需要先安装对应桌面 |
日志里提示xauth: file ... does not exist | Xauthority 路径不对,检查export XAUTHORITY |
日志里提示dbus-launch相关报错 | 缺少 dbus 会话环境,需要加 dbus-launch 包裹启动命令 |
看日志这个习惯救了我很多次,后面 x11vnc 出问题也是靠 journalctl 定位的,别嫌麻烦。
3. 权限和会话的连环坑:能连上桌面的并不代表能正常操作
3.1 桌面出来了,操作却像“隔了一层纱”
黑屏问题解决之后,我以为一切就要顺利了,结果新的问题马上来了:VNC 连上去确实能看到桌面,但鼠标点击没什么反应,键盘输入偶尔丢失,窗口也拖不动,整个桌面像一个只读的截图。
当时我一度怀疑是网络延迟,但本地局域网延迟根本不至于这么严重。后来仔细排查才发现,这个问题的根源不在网络,而在 X 会话的权限和桌面环境依赖。
X Window 系统有一套自己的授权机制,核心文件是~/.Xauthority。TightVNC 创建虚拟显示器的时候会生成自己的认证信息,但桌面进程真正运行起来还需要访问用户的 dbus 会话、密钥环等一系列服务。如果环境变量没有正确传递,特别是DBUS_SESSION_BUS_ADDRESS这个变量缺失,GNOME 类的桌面就会出现“只显示界面、无法操作”的诡异状态。
解决方案其实很简单,就是在 xstartup 里用 dbus-launch 把所有桌面进程包起来,让整个桌面会话跑在一个正确的 dbus 环境里。这也是为什么我在上一节的配置里特意加了dbus-launch --exit-with-session。
另外一个容易忽略的点是~/.Xauthority的权限。如果这个文件权限太宽,比如 644,其他本地用户就能读到你的授权 cookie,X 服务出于安全考虑会拒绝加载,反过来导致桌面组件起不来。我把它改成 600 之后,很多说不清的怪问题都消除了:
chmod 600 ~/.Xauthority3.2 为什么在 TightVNC 里我用 XFCE 而不是 GNOME
如果你测试过几轮就会发现,在 TightVNC 的虚拟显示器里启动 GNOME,经常出现各种小毛病:面板不见了、扩展加载失败、会话管理器报错。原因在于 GNOME 默认跟系统登录管理器深度绑定,依赖整个 systemd 用户会话流程,而 TightVNC 自己创建的虚拟显示器与这套流程是割裂的。
相比之下,XFCE 是一个轻量级桌面环境,对 dbus、systemd 的依赖小得多,启动速度快,远程场景下资源占用也更低。我装的这套配置里,XFCE 只需要一条命令就能在虚拟显示器上跑起来:
sudo apt install xfce4 xfce4-terminal可能有人会觉得 XFCE 没有 GNOME 漂亮,但远程办公场景下速度和稳定比那点视觉差异重要太多了。我后来一直用 XFCE 跑 TightVNC,再也没出现桌面“假死”的问题。
3.3 性能和色彩的几个参数建议
如果远程桌面操作还是觉得卡,可以从分辨率和色彩深度下手。把启动命令改成:
vncserver :1 -geometry 1280x720 -depth 16分辨率降低之后,需要传输的像素量大幅减少,-depth 16虽然会牺牲一些颜色精度,但日常开发、看文档完全够用。客户端那边也可以开启 JPEG 压缩选项,实测对延迟改善明显。
我最终的体验是:TightVNC 在局域网里是能用的,但上限摆在那里,如果单位网络复杂、跨网段访问频繁,卡顿会直接抹掉使用体验。这也是我后来下定决心换 x11vnc 的导火索之一。
4. 锁屏和无人值守之间的取舍
4.1 最让人崩溃的一幕:远程看到锁屏页而不是工作界面
TightVNC 跑顺之后,我自以为可以高枕无忧了。某一天我离开办公室,让电脑自己运行一个程序,回家后想用 VNC 远程看一眼进度。连上之后,屏幕上赫然是锁屏界面,需要输入密码,但我没有物理键盘,远程键盘输了半天也没法解锁,场面极其尴尬。
这个问题的本质其实是“锁屏锁的是物理显示器,而不是 VNC 虚拟显示器”。TightVNC 创建的:1虚拟会话,和物理屏幕:0的锁屏状态没有直接关系。也就是说,物理屏幕上锁没锁,虚拟会话完全不理会;反过来,虚拟会话里的桌面状态,也不代表物理屏上真的在发生什么。
如果你想要“远程给同事演示当前现场屏幕”或者“远程看到物理屏上正在跑的 GUI 程序”,TightVNC 这种虚拟会话模式从根本上就无法满足。这时候 x11vnc 的优势就体现出来了。
4.2 无人值守场景下的锁屏处理
如果你像我一样需要无人值守远程访问,最简单的做法是关闭自动锁屏。GNOME 环境下可以用 gsettings 调整:
gsettings set org.gnome.desktop.screensaver lock-enabled false gsettings set org.gnome.desktop.session idle-delay 0第一条关闭锁屏功能,第二条禁止空闲超时。这样无论物理屏还是虚拟会话,都不会在空闲时跳锁屏页。但这里必须强调安全性:关闭锁屏意味着任何能连到你这个 IP 和端口的人都可能直接看到桌面内容,所以下面这一步一定不能省。
4.3 防火墙只对可信网段开放
很多人配置完 VNC 顺手一行:
sudo ufw allow 5900/tcp这等于把 5900 端口对全世界开放,配合一个弱密码基本等于裸奔。我推荐用限定来源 IP 的方式:
sudo ufw allow from 192.168.1.0/24 to any port 5900 proto tcp这个命令的意思是只允许192.168.1.0/24这个内网网段的机器访问 5900 端口,其他来源一律丢弃。如果你有多台设备在外网需要连接,不要图省事直接全开,更稳妥的办法是走带认证的远程网关,而不是把端口裸奔到公网。
我后来为了兼顾“出门在外也能连”,在自己可控的路由器上只把特定来源网段转发到工作站,其余全部拒绝。折腾一圈之后你会发现,远程桌面最大的风险往往不是软件配置错,而是端口开放策略太随性。
5. x11vnc 的接入:把“虚拟屏”换成“真实屏”
5.1 压垮 TightVNC 的最后一件事
真正让我决定切换的,是一次现场调试。当时我在物理屏前启动了一个图形化软件,然后远程需要用 VNC 看这个软件的运行画面。结果可想而知,TightVNC 的虚拟会话里干干净净,什么都没有,因为那个软件跑在物理屏会话里,跟虚拟显示器完全不在一个世界。
这时候我才彻底明白:如果我要远程看到“当前这台机器实际屏幕上发生的一切”,就必须让 VNC 服务端直接读取物理显示器。x11vnc 干的就是这件事。
打个比方:TightVNC 是你在隔壁房间开了一个新办公室,远程的人看到的是新办公室的样子,和你在的原办公室无关;x11vnc 则像在原办公室装了一个直播摄像头,远程的人看到的就是你那间真实办公室的样子。对于要远程操作当前物理桌面的人来说,x11vnc 才是正确的工具。
5.2 安装、设置密码、手动启动验证
x11vnc 的安装同样简单:
sudo apt install x11vnc然后生成一个密码文件,以后 x11vnc 启动时直接从文件读认证信息:
sudo x11vnc -storepasswd 你的访问密码 /etc/x11vnc.pass注意密码文件权限要收一下,不然系统会拒绝加载。先手动跑一次,确认能够读取当前物理显示:
sudo x11vnc -display :0 -auth guess -rfbauth /etc/x11vnc.pass -forever -shared -noxdamage -rfbport 5900这里参数比较多,逐个解释一下:
-display :0:直接读取编号为 0 的物理显示器。-auth guess:让 x11vnc 自动猜 Xauthority 文件位置。这个参数极其关键,因为手动启动时我们可能不在图形会话环境里,没有它经常会报x11vnc: unable to open display :0。-forever:客户端断开后服务端不要退出,继续等待下一次连接。-shared:允许多个客户端同时连接同一画面。-noxdamage:关闭 XDamage 优化。部分显卡驱动下不开这个会导致画面不断闪烁,开了以后稳定很多。-rfbport 5900:显式指定监听端口。
如果一切顺利,终端会显示类似The VNC desktop is: 你的主机名:0的信息,用 VNC Viewer 连接同一个 IP 的 5900 端口,就能看到物理屏上的真实内容了。
5.3 把 x11vnc 做成开机自启服务
手动启动断掉终端就停了,不够靠谱,我把它写成了 systemd 服务。在/etc/systemd/system/x11vnc.service里放下面这份配置:
[Unit] Description=x11vnc remote desktop service After=network.target display-manager.service [Service] Type=simple ExecStart=/usr/bin/x11vnc -display :0 -auth guess -forever -shared -rfbauth /etc/x11vnc.pass -rfbport 5900 -noxdamage Restart=on-failure RestartSec=3 [Install] WantedBy=multi-user.target然后启用并启动:
sudo systemctl daemon-reload sudo systemctl enable --now x11vnc这里最值得注意的还是-auth guess。systemd 服务运行在系统上下文中,跟图形会话的环境完全隔离,它不知道 DISPLAY 是几,也不知道 Xauthority 文件在哪。如果不加这个参数,服务会反复尝试打开:0然后失败。加上-auth guess之后,x11vnc 会主动去常见位置寻找认证信息,大部分情况下都能直接搞定。
查看服务状态和端口监听情况:
systemctl status x11vnc ss -tlnp | grep 5900看到LISTEN状态就说明服务已经正常跑起来了。日志用journalctl -u x11vnc -n 50查看,出问题时别只看客户端提示,服务端日志往往已经写明了原因。
5.4 一个容易忽略的大前提:Wayland 会拦住 x11vnc
如果你用的是 Ubuntu 22.04 之后的版本,默认登录会话很可能是 Wayland,而 x11vnc 这类工具只能访问传统的 Xorg 显示服务器,在 Wayland 下会直接失败或黑屏。我在另一台机器上就撞了一次。
排查方法很简单,在图形终端里执行:
echo $XDG_SESSION_TYPE如果输出是wayland,那就意味着当前会话不是 Xorg。解决办法是登录界面上选择“Ubuntu on Xorg”再重新登录一次,切回 X11 会话后 x11vnc 才能正常工作。如果登录界面没有该选项,就需要确认对应桌面环境是否安装了额外的 Xorg 会话支持包。
这个前提如果不知道,配再多参数都是白搭。我见过有人折腾了两天最后发现根本不是配置问题,而是会话类型不对。
6. 这趟折腾之后,我留下的配置模板与避坑清单
6.1 一份可以直接照抄的最终配置模板
把前面所有内容浓缩成一份可复现的步骤,按顺序执行就行:
# 1. 安装工具 sudo apt update sudo apt install tightvncserver x11vnc xfce4 xfce4-terminal # 2. 配置 x11vnc 密码文件 sudo x11vnc -storepasswd 你的访问密码 /etc/x11vnc.pass sudo chmod 600 /etc/x11vnc.pass # 3. 配置 x11vnc 服务 sudo tee /etc/systemd/system/x11vnc.service > /dev/null <<'EOF' [Unit] Description=x11vnc remote desktop service After=network.target display-manager.service [Service] Type=simple ExecStart=/usr/bin/x11vnc -display :0 -auth guess -forever -shared -rfbauth /etc/x11vnc.pass -rfbport 5900 -noxdamage Restart=on-failure RestartSec=3 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now x11vnc # 4. 防火墙限制来源网段 sudo ufw allow from 192.168.1.0/24 to any port 5900 proto tcp执行完之后,用 VNC Viewer 连接主机IP:5900,输入密码就能看到物理桌面了。
6.2 踩坑速查表
| 症状 | 可能原因 | 解决动作 |
|---|---|---|
| TightVNC 连接后黑屏 | xstartup 没配置或没启动桌面 | 补全 ~/.vnc/xstartup 并 chmod +x |
| 连接后看到桌面但无法点击 | dbus 会话环境缺失 | 用 dbus-launch 包裹桌面启动命令 |
| 操作卡顿、颜色花 | 分辨率和色深太高 | 降低分辨率和色彩深度 |
| 远程看到锁屏界面 | 无人值守前未关闭自动锁屏 | 用 gsettings 关闭锁屏 |
| x11vnc 无法打开 :0 | 缺少 Xauthority 信息 | 加上 -auth guess |
| Wayland 下 x11vnc 黑屏 | 会话不是 Xorg | 登录界面切到 Ubuntu on Xorg |
| 服务启动成功但外网连不上 | 防火墙未放行或来源受限 | 检查 ufw 规则和监听端口 |
6.3 几个我后悔没早点知道的习惯
配置完之后,我养成了三个习惯。第一,修改任何 VNC 相关配置后,一定要看服务日志,而不是反复重试验证;TightVNC 看~/.vnc/*.log,x11vnc 看journalctl -u x11vnc。第二,不要贪图省事把防火墙端口全开,限网段、强密码、小权限是底线。第三,所有配置文件改动之前先备份,尤其是 xstartup 和 systemd 服务文件,一次改错还能快速回滚。
整个折腾下来的最大体会是:远程桌面的坑,大多不是软件安装问题,而是对“虚拟屏幕”和“真实屏幕”的模型没分清。如果你一开始就知道自己是要远程查看物理桌面,那直接上 x11vnc,别在 TightVNC 的虚拟会话里浪费时间;如果你只是需要一个跟物理屏无关的独立工作环境,再考虑 TightVNC。现在我这台工作站已经稳定跑了两个多月,无论在家还是在办公室,都能随时看到现场画面,再也没出现过黑屏或者锁屏卡死的闹剧。