Ubuntu 20.04 VNC远程桌面实战:TigerVNC选型、黑屏与自启 📅 发布时间:2026/9/19 1:23:59 👁 浏览次数: 1. 为什么 Ubuntu 20.04 上的 VNC 方案要先挑对再动手远程访问一台 Ubuntu 机器的图形界面最常见的翻车现场不是装不上而是装完之后客户端连上了、密码也过了屏幕上却是一片纯黑或者只有一个孤零零的终端窗口。很多人第一反应是配置写错了然后开始疯狂改xstartup改到最后连哪个文件是有效的都搞不清。我前后在十几台机器上折腾过这套东西从 16.04 一路用到 22.04结论很明确Ubuntu 20.04 上跑 VNC方案选型占七成配置只占三成。选错组件后面所有调试都是在填坑。这篇内容面向的是需要在 Ubuntu 20.04桌面版或带 GUI 的服务器版上开启远程图形访问的开发者、测试人员和运维同学。不管你是想远程跑一下 IDE、看个仿真界面还是做自动化测试需要图形环境下面的整套流程都可以直接照着复现。默认你会用sudo也默认你至少能通过 SSH 登录这台机器——后面所有操作都是命令行完成的不需要坐在机器前面。1.1 vnc4server 和 tightvnc 在 20.04 上已经不合时宜你在搜索引擎里翻到的绝大多数中文教程发布时间大概在 2015 到 2018 年之间里面写的都是apt install vnc4server或者apt install tightvncserver。这两条命令在 Ubuntu 20.04 上还能装但装完之后的问题非常密集。vnc4server这个包在 Ubuntu 20.04 的官方源里其实已经不存在了apt会直接报Unable to locate package。有些教程会让你去下载.deb手动装装是能装上但它依赖的Xvnc是基于很老的 X 服务器分支跟 20.04 默认的 GNOME 3.36 会话配合时gnome-shell经常直接崩溃表现为连接后黑屏几秒然后断开。tightvncserver虽然还在源里但它对现代的 X 扩展支持不完整尤其是缺少XKB相关的更新会导致键盘映射错乱——你敲a出来的是别的字符或者修饰键完全失效。我最早就是用 tightvnc 起步的被键盘问题折磨了一下午才换掉。1.2 TigerVNC 和 x11vnc 到底该选哪个目前在 Ubuntu 20.04 上真正值得用的只有两个TigerVNC和x11vnc。它们不是同一类东西很多人一开始就搞混了。TigerVNC 是独立会话模式。它自己拉起一个新的 X 服务器实例你在 VNC 里看到的桌面和你坐在物理显示器前看到的桌面是两个完全独立的会话。好处是互不干扰你甚至可以同时开:1、:2两个会话坏处是你在这边打开的程序在物理屏幕上找不到。x11vnc 是镜像共享模式。它把已经运行的那个物理 X 会话直接共享出去你在 VNC 里看到的就是物理屏幕上的画面鼠标动一下两边同步。代价是它依赖那个已经存在的 X 会话如果机器重启后没人登录图形界面x11vnc 就没有东西可以共享。我的建议很直接需要远程操作一个真实存在的桌面选 x11vnc需要一台无头机器长期提供图形环境选 TigerVNC。下面整套流程以 TigerVNC 为主线因为它的适用场景更广也更容易做成开机自启。1.3 动手前必须确认会话类型是 Xorg 还是 Wayland这是被 90% 的教程跳过的一步也是 20.04 上最容易让人白忙活的地方。Ubuntu 20.04 默认使用Wayland作为显示服务器而所有基于 X 的 VNC 方案包括 TigerVNC在 Wayland 会话下都无法正常工作。你得先确认当前登录的会话类型命令很简单echo $XDG_SESSION_TYPE loginctl show-session $(loginctl | grep $(whoami) | awk {print $1}) -p Type如果输出是wayland你需要切回 Xorg。改法不是去改环境变量而是修改 GDM 的配置文件sudo nano /etc/gdm3/custom.conf把这一行前面的注释符号去掉WaylandEnablefalse然后重启机器。重启后重新登录再执行一次上面的命令确认输出变成x11。注意这一步改了之后整个系统的图形会话都会跑在 Xorg 上不只是 VNC 用得到。对于开发机来说这通常没什么影响反而能避开 Wayland 下一些截图工具和录屏工具的兼容问题。2. 从 apt 装包到 5901 端口跑通的全过程选型确定之后安装本身其实只有几分钟。但这里有几个细节如果你不注意会在后面排查故障时多绕很多弯路。我习惯把安装拆成装包、设密码、首次启动、验证端口四步每一步都留下可验证的输出出问题时就能快速定位到是哪一层断掉了。2.1 装包与轻量桌面环境的取舍先更新索引再安装sudo apt update sudo apt install -y tigervnc-standalone-server tigervnc-common tigervnc-tools三个包的分工是tigervnc-standalone-server提供Xvnc和vncserver脚本tigervnc-common提供vncpasswd等工具tigervnc-tools里有vncviewer之类的辅助程序。装完之后可以用dpkg -l | grep tigervnc确认版本Ubuntu 20.04 源里对应的是 1.10.x。接下来是我强烈建议做的一件事别直接用默认的 GNOME 会话当 VNC 桌面。原因很实际——gnome-shell需要 3D 加速而 TigerVNC 提供的是软件渲染的虚拟显示两者配合时经常出现窗口管理器启动失败、顶栏不渲染、拖窗口有严重残影等问题。我试过各种绕法包括用gnome-session --sessionubuntu和各种环境变量 hack效果都不理想。更省心的做法是额外装一个轻量桌面sudo apt install -y gnome-flashback # 或者用更轻的 XFCE sudo apt install -y xfce4 xfce4-goodiesgnome-flashback是 GNOME 的经典模式用的是metacity窗口管理器对软件渲染友好界面跟 GNOME 2 类似实际用起来完全不别扭。XFCE 更轻资源占用小适合配置不高的虚拟机。我个人的默认选择是gnome-flashback因为它跟 Ubuntu 的主题和字体已经统一好了不用再单独折腾外观。2.2 用 vncpasswd 设置密码并理解它的长度限制密码必须用这个专用命令设置不能手写文件vncpasswd它会让你输入两遍密码然后问一个view-only password这个直接按n跳过。设置完成后会在~/.vnc/目录下生成一个passwd文件。这里有个必须知道的事实VNC 协议本身的认证密码只取前 8 个字符。你输入 20 位密码第 9 位开始全部被忽略。这不是 TigerVNC 的 bug是 RFB 协议的历史遗留设计。所以别指望靠长密码保安全真正的防护手段是限制监听地址或者叠加 SSH 端口转发——这个放到第 5 章细说。顺便说一句~/.vnc/passwd的权限会被自动设成 600不要手动改成 644否则vncserver会拒绝加载并报WARNING: The VNC server is not password protected。2.3 首次启动和显示号、端口的换算关系首次启动之前先手动建一个空的~/.vnc/xstartup占位防止脚本报找不到文件mkdir -p ~/.vnc touch ~/.vnc/xstartup chmod x ~/.vnc/xstartup然后启动第一个会话vncserver :1 -geometry 1920x1080 -depth 24这条命令里的参数含义分别是:1是显示号-geometry决定虚拟屏幕分辨率-depth是颜色深度。启动成功后终端会输出类似这样的内容New machine-name:1 (youruser) desktop is machine-name:1 Starting applications specified in /home/youruser/.vnc/xstartup Log file: /home/youruser/.vnc/machine-name:1.log这里有个新手最容易晕的点显示号:1对应的端口是 5901不是 5900。换算规则是端口 5900 显示号。所以:1→ 5901:2→ 5902:10→ 5910。客户端连接时要填地址:1或者地址:5901两种写法都可以但填错端口号是连不上这类问题里最高频的原因。验证监听状态ss -tlnp | grep 590正常应该看到Xvnc进程监听在*:5901或者0.0.0.0:5901。如果只看到127.0.0.1:5901说明启动时带了-localhost参数只有本机能连这一点在后面配置 systemd 时会用到。3. xstartup 是黑屏和灰屏的唯一嫌疑人到这一步如果你的vncserver启动没报错、端口也在监听但客户端连上去是黑屏、灰屏、只有一个终端窗口那么问题 100% 出在~/.vnc/xstartup。这个脚本是 VNC 会话启动时执行的入口它决定了桌面长什么样。3.1 xstartup 的执行时机和它到底在干什么vncserver脚本在初始化一个显示号时做的事情大致是启动Xvnc进程 → 加载~/.vnc/passwd→ 执行~/.vnc/xstartup→ 把xstartup的输出重定向到~/.vnc/*.log。所以xstartup本质上就是一个 shell 脚本它运行在Xvnc提供的那个 X 会话里。脚本里启动的最后一个程序如果是长期运行的比如窗口管理器或桌面会话vncserver就会认为会话正常运行如果脚本跑完就退出了Xvnc会认为没有客户端然后把会话关掉——这就是闪退现象的成因。默认生成的xstartup内容非常简陋大概只有xrdb和twm几行。twm是一个上古时期的窗口管理器退化到连窗口边框都很丑很多教程里看到的灰底加一个十字光标就是它。你要做的就是把这几行换成你要用的桌面环境的启动命令。3.2 一份能跑起 gnome-flashback 的 xstartup下面这份是我在 20.04 上实测可用的版本用的是gnome-flashback#!/bin/sh # 清理可能冲突的会话变量 unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS # 明确告诉应用这是 X11 会话 export XDG_SESSION_TYPEx11 # 加载系统级的 X 资源 [ -x /etc/vnc/xstartup ] exec /etc/vnc/xstartup [ -r $HOME/.Xresources ] xrdb $HOME/.Xresources # 启动 VNC 的配置托盘工具 vncconfig -iconic # 启动 GNOME Flashback 会话 dbus-launch --exit-with-session gnome-session --sessiongnome-flashback-metacity逐行解释几个关键点。unset SESSION_MANAGER和unset DBUS_SESSION_BUS_ADDRESS是为了避免脚本继承了物理会话的环境变量导致新会话以为自己已经存在从而拒绝启动。XDG_SESSION_TYPEx11是给那些检查会话类型的应用一个明确的答案不设的话某些 GTK 应用会走 Wayland 分支然后连不上显示。dbus-launch --exit-with-session是必须的。GNOME 会话严重依赖 D-Bus缺了它会出现能启动但没有顶栏、设置打不开、终端能开但一关就崩这类诡异症状。--exit-with-session表示当会话退出时自动清理 D-Bus 守护进程防止残留。如果你选的是 XFCE最后一行换成exec startxfce4XFCE 不需要dbus-launch包装直接用startxfce4就能起来更简单。改完记得给执行权限chmod x ~/.vnc/xstartup3.3 黑屏、灰屏、闪退三类现象的排查链路这三种现象成因完全不同别混在一起调。我按从现象推原因的顺序列一下我实际排查过的路径。纯黑屏鼠标能动但什么都没有说明Xvnc起来了xstartup也执行了但桌面会话没接管屏幕。先看日志~/.vnc/*.log如果看到gnome-session: command not found说明装的包不对如果看到Failed to connect to session manager基本就是上面说的 D-Bus 问题。另外检查一下是不是漏了XDG_SESSION_TYPE。灰底加网格或者只有一个终端窗口这是xstartup根本没被替换还在跑默认的twm。直接cat ~/.vnc/xstartup确认内容很多情况下是你改了文件但忘了加执行权限或者改的是另一个显示号的配置。连上两秒然后断开xstartup里的程序启动失败后立刻退出Xvnc检测到没有客户端就关掉了会话。打开日志看最后几行报错常见的是窗口管理器的命令名写错了比如gnome-flashback的会话名在不同版本里不一样。可以用ls /usr/share/gnome-session/sessions/看有哪些可用的会话文件把对应的名字填进去。提示每次改完xstartup都要先杀掉旧会话再重启否则改的东西不会生效。命令是vncserver -kill :1然后重新vncserver :1。4. 用 systemd 托管 VNC 会话开机自启与日志定位手动vncserver :1的方式适合调试但绝对不适合长期使用。机器一重启会话就没了而且一旦终端断开你也不确定进程还在不在。正确做法是交给 systemd 管理。4.1 为什么不用 rc.local 或者 crontab 启动我见过不少教程教你在rc.local里加一行vncserver :1或者用crontab的reboot。这两种方式在 20.04 上都不推荐原因有两个。一是执行时机不对。rc.local在内核启动早期运行那时候用户的家目录可能还没挂载好网络也可能还没起来vncserver会因为找不到.vnc目录或者无法解析主机名而失败。crontab虽然晚一点但环境变量是精简过的PATH里没有/usr/bin之外的路径dbus-launch这类命令经常找不到。二是管理不了生命周期。会话崩了不会自动重拉想看日志得自己去找.vnc/*.log还容易被日志轮转删掉。systemd 这几件事全都解决了而且开机自启只需要一条enable。4.2 一份可直接使用的 systemd 单元文件在/etc/systemd/system/下创建vncserver.service注意文件名里的是模板占位符[Unit] DescriptionTigerVNC Remote Desktop Service for display %i Afternetwork.target syslog.target [Service] Typeforking User%i Group%i WorkingDirectory/home/%i ExecStartPre/bin/sh -c /usr/bin/vncserver -kill :1 /dev/null 21 || : ExecStart/usr/bin/vncserver :1 -geometry 1920x1080 -depth 24 -localhost no ExecStop/usr/bin/vncserver -kill :1 Restarton-failure RestartSec5 PIDFile/home/%i/.vnc/%H:1.pid [Install] WantedBymulti-user.target几个参数值得说明。%i会被实例名替换所以启动时写systemctl start vncserveryouruserUser和Group就自动变成youruser家目录也是对应的一个模板文件能服务多个用户。ExecStartPre里那段|| :的写法是为了让命令即使失败也返回成功因为第一次启动时本来就没有会话可以 kill不这样写 systemd 会直接判定启动失败。-localhost no表示允许非本机地址连接。这个参数在 TigerVNC 1.10 上支持如果你用的是更老的版本报参数错误把这一段去掉即可默认是监听所有地址。但从安全角度讲更推荐保留-localhost默认行为然后用 SSH 端口转发来访问这个下一章会讲。Typeforking是因为vncserver脚本会 fork 出Xvnc进程后自己退出。配合PIDFile指向.vnc/%H:1.pidsystemd 才能正确跟踪到真正的服务进程。4.3 启用服务并用 journalctl 定位启动失败创建完文件后重新加载配置sudo systemctl daemon-reload sudo systemctl enable vncserver$(whoami) sudo systemctl start vncserver$(whoami)检查状态sudo systemctl status vncserver$(whoami)如果显示active (running)说明服务已经托管成功。这时候可以做一次完整的验证sudo reboot重启后再看状态仍然是 running 且端口在监听就说明开机自启配置没问题了。如果状态是failed先看 systemd 的日志sudo journalctl -u vncserver$(whoami) -n 50 --no-pager这份日志只包含vncserver脚本层面的输出比如找不到命令、参数错误、权限不足。如果 journalctl 里看不到具体的桌面启动错误那就要去看 TigerVNC 自己写的日志cat ~/.vnc/*:1.log这里才是xstartup里各个程序的真实输出。我遇到过的一个典型情况是systemd 启动时$HOME环境变量没被正确传递导致dbus-launch找不到用户会话总线日志里一堆Failed to open connection to session bus。解决办法是在 Service 段落里显式加一行EnvironmentHOME/home/%i。5. 连接侧客户端、端口转发与分辨率调整服务端跑通了接下来是连接侧。这一层的问题通常表现得比较粗暴——直接连不上或者连上了但画质和延迟让人没法用。5.1 客户端软件选择与分层排查思路常见的客户端有 RealVNC Viewer、TigerVNC Viewer、Remmina 等。我个人的偏好是 TigerVNC Viewer因为跟服务端同源兼容性最省心如果是在 Windows 或 Mac 上办公RealVNC Viewer 的安装和界面体验更好免费版功能足够。连不上时别急着改服务端配置按这个顺序排查效率最高。先确认服务端进程和端口sudo systemctl status vncserver$(whoami) ss -tlnp | grep 590再确认防火墙。Ubuntu 默认的ufw如果开着需要放行sudo ufw status sudo ufw allow 5901/tcp然后是网络可达性。从客户端机器上ping一下服务端 IP再telnet ip 5901或者用nc -vz ip 5901测端口。端口不通但 ping 得通问题基本在防火墙或者服务端监听地址上。最后才考虑客户端配置。一个很容易忽略的坑是颜色深度不匹配——服务端用-depth 24启动客户端却选了 8-bit 模式连上后画面会花得没法看。5.2 通过 SSH 端口转发访问 VNC 的配置方法前面提到 VNC 的密码保护只有 8 位有效字符而且 RFB 协议早期版本的认证握手在很多场景下是明文传输的。如果这台机器不是完全隔离的内网环境强烈建议把 VNC 的监听限制在本地通过 SSH 端口转发来访问。服务端启动参数改成默认的-localhost行为也就是只监听127.0.0.1:5901。然后在客户端执行ssh -L 5901:127.0.0.1:5901 -N -f youruserserver-ip这条命令的含义是在本地开一个 5901 端口把所有流量通过 SSH 加密转发到服务端的127.0.0.1:5901。-N表示不执行远程命令-f表示后台运行。然后客户端 VNC Viewer 连接localhost:5901就行。这样做的额外好处是 SSH 的认证机制本身就足够强VNC 那 8 位密码就变成了第二道无关紧要的门即使被猜到没有 SSH 密钥也进不来。如果服务端和客户端之间有跳板机还可以叠加-J参数做多级跳转原理是一样的。5.3 分辨率、剪贴板和多会话残留的处理分辨率不是随便填的。你填的-geometry决定了虚拟屏幕的大小但如果这个尺寸超过客户端窗口显示区域你会看到滚动条填得太小又会很憋屈。1920x1080 是一个比较通用的起点笔记本屏幕建议用1600x900或1440x900。TigerVNC 支持动态调整分辨率客户端菜单里有Resize remote session之类的选项但前提是xstartup里启动了支持 RandR 的窗口管理器gnome-flashback和 XFCE 都支持。剪贴板共享需要在服务端跑vncconfig -iconic 也就是前面xstartup里的那一行。如果发现复制粘贴不工作先确认这个进程在不在ps aux | grep vncconfig。缺了就补上。多会话残留是个容易被忽略的问题。反复vncserver :1而不 kill 掉旧的会生成:2、:3每个都占内存和端口。查当前运行的会话vncserver -list清理全部vncserver -kill :*但注意重启机器后.vnc目录里的锁文件和 PID 文件可能还在如果这时用同样的显示号启动会报A VNC server is already running as :1。删掉残留的锁文件即可rm -f /tmp/.X1-lock /tmp/.X11-unix/X16. 一张故障对照表和我实际踩过的几个细节把前面散落的排查点整理成表出问题的时候可以对照着看比从头翻文档快得多。6.1 常见报错与对应处理现象大概率原因处理方式Unable to locate package vnc4server包在 20.04 源中已移除改用tigervnc-standalone-server客户端连上即断开xstartup程序启动失败后退出查~/.vnc/*.log最后几行报错纯黑屏无任何界面桌面会话未接管常见于 D-Bus 缺失xstartup中补dbus-launch --exit-with-session灰底加十字光标仍在跑默认的twm替换xstartup内容并加执行权限A VNC server is already running as :1锁文件残留删除/tmp/.X1-lock和/tmp/.X11-unix/X1键盘字符错乱旧版 VNC 的 XKB 支持不完整切换到 TigerVNC 1.10 及以上服务重启后会话消失未配置 systemd 自启创建vncserver.service并enable客户端能连但画面卡顿颜色深度或压缩级别设置不当服务端用-depth 24客户端选Tight或ZRLE编码6.2 部署过程中值得记住的几条经验第一条改配置前先备份~/.vnc/xstartup。这个文件不大但一旦被改乱重新推导出正确内容要花不少时间。养成习惯cp ~/.vnc/xstartup ~/.vnc/xstartup.bak再动手。第二条日志一定要看别猜。我早期排查黑屏问题时来回改了六七次xstartup最后发现日志里早就写了gnome-session: not found——装gnome-flashback的时候漏了一个依赖包。~/.vnc/*.log和journalctl加起来一共两处日志覆盖了从服务启动到桌面初始化的全部环节养成先看日志再动手的习惯能省掉大量无效尝试。第三条虚拟机的显卡配置会影响体验。如果 Ubuntu 跑在 VMware 或 VirtualBox 里3D 加速开关状态会影响某些桌面环境的渲染。用gnome-flashback这类不依赖硬件加速的桌面可以规避这个问题这是我在虚拟机里反复验证过的结论。第四条不要在同一个显示号上叠加多个配置。有些人会在/etc/vnc/xstartup和~/.vnc/xstartup里都写启动命令结果两个脚本都执行了一遍桌面试图启动两次然后互相冲突。记住xstartup里的[ -x /etc/vnc/xstartup ] exec /etc/vnc/xstartup这行如果系统级脚本存在它会用exec替换掉当前进程你写在后面的内容根本不会执行。我在一台机器上因为这个卡了很久最后发现是系统级文件在起作用。第五条如果这台机器只是偶尔远程用一下其实可以考虑更省事的替代路径——比如直接用带 X11 转发能力的 SSH 客户端通过ssh -X单独转发某个图形程序不需要完整的远程桌面。VNC 的价值在于完整桌面体验如果你的需求只是跑一两个 GUI 工具ssh -X的配置成本几乎为零。这个取舍值得在动手前想清楚。