前段时间帮一位做嵌入式的老哥处理远程开发机的问题他人不在实验室但那台 Ubuntu 20.04 的工作站上开着串口调试终端、Zephyr 的编译窗口和好几份文档光靠 SSH 根本看不到图形界面。最后用 VNC Server 把整块桌面搬到了他的笔记本上改代码、看串口日志、跑仿真跟在现场几乎没差别。这事之后我才意识到Ubuntu 20.04 安装 VNC Server看着像一条再普通不过的命令行操作真动手时踩的坑一点都不少——连上了黑屏、只有终端没桌面、键盘鼠标没反应、整机重启后服务消失。这篇就把我这些年在这套系统上配 VNC 的完整流程、参数取舍和翻过的车一次讲透。不管你是刚装完虚拟机的新手还是天天泡在服务器堆里的老手照着走基本能一次跑通。1. 先把 VNC 的定位想明白再动手装1.1 VNC、SSH、远程桌面三者各管什么很多人一上来就问装了 VNC 是不是就不需要 SSH 了其实这两个东西的定位完全不同。SSH 给你的是一个字符终端好处是轻、快、稳几 KB 的带宽就能跑编译、改配置文件、看日志这些活它全能干。但它有个硬边界——凡是要看到像素的活它都干不了IDE 的图形窗口、浏览器调试、图像处理、单片机 IDE 里的下载按钮这些东西在纯终端里没法操作。VNC 补的正是这块。它做的是整屏像素的搬运服务端把当前桌面渲染成一帧帧图像压一压发给你客户端再把你的鼠标键盘事件回传。你看到的就是那台机器屏幕上的样子操作逻辑和坐在它面前一模一样。代价是它吃带宽、有延迟画面变化剧烈时会更明显。所以我的习惯一直是两个都装、都开着日常改代码走 SSH需要看界面的时候再开 VNC。另外别把 VNC 和微软的 RDP、向日葵那类工具混为一谈协议不同、端口不同、体验也不同RDP 在局域网里通常更顺滑但跨系统的兼容性和纯开源可自建这一点上VNC 更省心。理解了这个分工你就知道什么时候该用它也就不会因为连上了但卡而怀疑自己配错了。还有一点容易忽略VNC 默认只搬运画面不搬运声音。想让它出声得额外配 PulseAudio 转发绝大多数远程改代码的场景根本用不上所以我一般直接跳过把复杂度留给真正需要的功能。1.2 为什么这套流程我推荐 TigerVNCLinux 上的 VNC 服务端有好几个流派常见的有 TigerVNC、x11vnc、vino、tightvnc。我这些年主力用 TigerVNC原因很实在。第一是它自带独立的 X 会话。也就是说你连上去之后看到的是一块虚拟屏幕跟你物理显示器上开着的桌面互不干扰。你在这块虚拟屏里跑什么物理屏上不会跟着动多人同时在服务器上开各自的 VNC 会话也不打架。做嵌入式开发的朋友经常需要一边在物理屏挂着示波器软件一边在虚拟会话里编译这种场景下独立会话就是刚需。第二是它在新版 Ubuntu 上的兼容性相对好包在官方源里就有不用加第三方仓库安装和升级都干净。第三是它支持通过配置文件统一管理分辨率、色深、监听地址这些参数方便你后面写进 systemd 让它开机自启。x11vnc 也不是不好它的强项是共享物理桌面上已经开着的那块屏适合我人就坐在机器前只想把眼前这块屏推给别人看的场景比如演示、远程协助。但它抓屏幕的能力在 Wayland 会话下会直接失效这个坑后面单独说。对绝大多数想给 Ubuntu 20.04 加一块随时能连的远程桌面的需求TigerVNC 独立会话是更省事的选择。当然也有例外后面第 6 节我会把 x11vnc 的用法也补全你按自己的场景挑。2. 装之前的三项确认省掉一半返工2.1 先确认会话是 Xorg 还是 Wayland这是整个流程里最容易被跳过、也最容易导致后续所有努力白费的一步。Ubuntu 20.04 的默认登录会话其实是 Xorg所以大部分情况下你是安全的。但如果你是从更早的版本升级上来的或者手动在登录界面右下角的小齿轮里切换过就可能是 Wayland。为什么不确认不行因为 x11vnc 这类靠抓取 X 屏幕工作的服务在 Wayland 会话下抓到的往往是一片黑。TigerVNC 的独立会话受影响小一些但一些依赖 X11 的组件仍可能出问题。确认方法很直接登录桌面后打开终端敲echo $XDG_SESSION_TYPE返回x11就是 Xorg返回wayland就得注意了。如果是后者注销回到登录界面点右下角齿轮图标选择Ubuntu on Xorg再登录然后重新执行上面的命令确认一次。这个动作只需要做一次之后系统会记住你的选择。顺手再确认一下桌面的类型这对第 3 节写 xstartup 很关键echo $XDG_CURRENT_DESKTOPUbuntu 20.04 默认会输出ubuntu:GNOME。记住这个值后面配置时要和它对应。2.2 更新源与必备依赖动手前先把软件源刷一遍避免因为索引过期装不上包或者装到一半报依赖冲突sudo apt update sudo apt upgrade -y这里有个经验如果你所在的网络对某些源响应很慢可以先去软件和更新里把下载服务器换一个更近的镜像站速度能差出好几倍。升级过程如果内核有更新建议先重启一次再装 VNC免得拿着旧内核跑新装的显卡驱动类依赖出一些莫名其妙的问题。另外确认一下系统架构虽然 20.04 主流都是 amd64但在树莓派或者某些 ARM 盒子上跑的话是 arm64包名一样但依赖不同uname -m如果输出x86_64就走常规流程aarch64就是 ARM 平台后面涉及的包都通用不用担心。2.3 想清楚从哪台机器连过来这一步不是技术必需但决定了你后面要不要加密、要不要做额外配置。如果连接的机器和服务端在同一个局域网比如你家路由器下的两台电脑或者公司同一子网里那直接连 IP 加端口就行速度最快、延迟最低。如果两边不在同一个网络就得想想怎么让流量安全地走。VNC 协议本身的密码认证是质询-响应式的认证过程不传输明文密码但它对整条会话内容并不加密。所以跨公网直连在安全上并不理想。我自己的做法永远是服务端的 VNC 只监听本机然后用 SSH 隧道把端口转发出来这也是第 5.3 节要展开的内容。把这个前提想清楚你后面配~/.vnc/config里的监听地址时就不会纠结了。局域网用就设成监听所有网卡跨网络用就老老实实绑在本机配合隧道。3. TigerVNC 安装与 xstartup 配置实录3.1 安装主程序并设置访问密码包很干净两条命令搞定sudo apt install -y tigervnc-standalone-server tigervnc-common装完之后先设置访问密码这一步会生成~/.vnc/passwd文件vncpasswd它会让你输两遍密码注意这个密码长度限制是 8 位以内超过部分会被截断所以别设一个 12 位的复杂密码然后自己都记不住截断后是哪 8 位。输完之后它会问你要不要设一个只读密码这个密码进去只能看不能操作用来做演示或者给别人围观挺方便个人自用直接回车跳过即可。密码文件生成在家目录的.vnc隐藏目录里权限是 600这是对的别手动去改它的权限否则有些版本会因为权限过松拒绝加载。注意这里的密码是用来连 VNC 的跟你系统的登录密码是两码事别设成一样的也别图省事设成 12345678。3.2 写对 xstartup黑屏灰屏的根源在这.vnc/xstartup是整套配置的心脏绝大多数连上了却是灰屏或者只有鼠标没有桌面的问题都出在这里。它决定了 VNC 会话启动时具体拉起哪个桌面环境。先说一个我踩过的坑网上大量老教程给的 xstartup 是给旧版 GNOME 或者干脆是给 Xfce 写的直接抄到 Ubuntu 20.04 的 GNOME 上大概率得到一个灰底加一个 X 形光标或者干脆黑屏。原因是新版 GNOME 的会话启动方式变了需要先清掉几个环境变量再拉起。给 Ubuntu 20.04 原生 GNOME 用的版本我实测比较稳的是这样#!/bin/sh unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS export XDG_CURRENT_DESKTOPGNOME export XDG_SESSION_TYPEx11 [ -r $HOME/.Xresources ] xrdb $HOME/.Xresources vncconfig -iconic dbus-launch --exit-with-session gnome-session 第一行和第二行的unset非常关键。SESSION_MANAGER和DBUS_SESSION_BUS_ADDRESS是物理登录会话留下的环境变量如果不清掉VNC 会话里的桌面会去连物理会话的会话总线结果就是启动到一半卡死或者直接退出。这个问题很隐蔽日志里往往只有一句含糊的报错不细看根本发现不了。vncconfig -iconic 那行负责剪贴板双向同步少了它你在本地复制的命令粘贴不进远程终端用起来会非常别扭。还有一个更省心的路线如果你对桌面环境没有执念纯粹是想要一个能跑图形程序的远程环境那直接装一个轻量的 Xfce 专用给 VNC物理机上还是用 GNOME两边互不影响sudo apt install -y xfce4 xfce4-goodies对应的 xstartup 就简单得多#!/bin/sh unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS exec startxfce4这样能绕开 GNOME 会话在远程下的很多启动问题资源占用也低连老笔记本远程过去都挺流畅。代价是桌面风格跟 Ubuntu 原生不一样看你能不能接受。最后千万别忘了给脚本加执行权限这是另一个高频翻车点chmod x ~/.vnc/xstartup3.3 首次启动与日志查看配置写好后先手动启动一次确认没问题再上 systemdvncserver :1 -geometry 1920x1080 -depth 24:1是会话编号对应端口 5901这个映射关系后面会说。启动成功它会打印一行类似New ubuntu:1 (user) desktop is ubuntu:1的提示看到这行基本就成了。万一起不来第一件事是看日志位置在~/.vnc/主机名:编号.log比如~/.vnc/ubuntu:1.log。里面会记录桌面启动的详细过程gnome-session报错、找不到命令、权限不足这类问题基本都能在这里找到线索。养成看日志的习惯比在网上乱搜半天快得多。想停掉当前会话vncserver -kill :14. 分辨率、端口与开机自启4.1 分辨率、色深与 config 文件每次启动都敲一长串参数很烦把这些固化的配置写进~/.vnc/config更省事geometry1920x1080 depth24 localhostnogeometry是分辨率按你客户端屏幕来定笔记本一般 1920x1080 够用2K、4K 屏就相应往上写。但要注意分辨率开太高会显著增加带宽占用画面变化时延迟更明显局域网内问题不大跨网络时建议降一档。depth是色深24 位色是主流选择画质和带宽比较平衡。低于 16 位颜色会明显发虚图标的渐变色会变成色块设到 32 位对画质提升有限带宽却会再涨一截我更推荐老老实实 24。localhostno是控制监听地址的设为no表示监听所有网卡局域网内可以直接连。如果你打算走 SSH 隧道这个值设成yes更安全服务只监听本机外部必须经过隧道才能访问。这个取舍后面还会讲。注意把localhost写成localhostno而不是localhost no中间带空格在某些版本上会导致解析失败这个坑我不想再踩第二次。4.2 端口号与多会话管理VNC 的端口规则很简单5900 会话编号。会话:1对应 5901:2对应 5902以此类推。:0对应 5900一般留给物理桌面共享用独立会话从:1起。这个编号体系的好处是你能同时开多个独立会话给不同用途。比如开一个:1跑全屏 IDE开一个:2专门跑串口终端和下载工具两个窗口各连各的互不干扰。查看当前有哪些会话在跑vncserver -list想给不同会话配不同分辨率也行启动时分别指定即可vncserver :1 -geometry 1920x1080 -depth 24 vncserver :2 -geometry 1280x800 -depth 24防火墙这边Ubuntu 20.04 如果开了 ufw得把对应端口放行。局域网直连场景sudo ufw allow 5901/tcp走 SSH 隧道的话VNC 端口压根不用对外放行只放 SSH 的 22 就行安全性反而更高。这也是我为什么偏爱隧道方案。4.3 用 systemd 托管重启不掉线手动启动的会话在服务器重启后就没了得重新敲命令。交给 systemd 管起来最省心。新建一个模板服务文件sudo nano /etc/systemd/system/vncserver.service内容如下记得把YOUR_USER换成你自己的用户名[Unit] DescriptionRemote desktop service (VNC) Aftersyslog.target network.target [Service] Typeforking UserYOUR_USER GroupYOUR_USER WorkingDirectory/home/YOUR_USER ExecStartPre/bin/sh -c /usr/bin/vncserver -kill %i /dev/null 21 || : ExecStart/usr/bin/vncserver %i ExecStop/usr/bin/vncserver -kill %i [Install] WantedBymulti-user.target里面%i是实例占位符启动时把会话编号传进去。ExecStartPre那行的作用是先清掉可能残留的同编号会话避免启动时因为旧进程占用而失败这个防御性写法能省掉很多重启后服务起不来的玄学问题。然后重新加载并启用sudo systemctl daemon-reload sudo systemctl enable vncserver:1.service sudo systemctl start vncserver:1.service看一眼状态确认跑起来了sudo systemctl status vncserver:1.service之后不管怎么重启会话都会自动恢复。有一点要提醒用 systemd 托管时会话是以你的用户身份跑的所以~/.vnc下的 password 和 xstartup 必须是你这个用户能读能执行的权限不对同样会起不来。5. 客户端连接与体验调优5.1 客户端选择与连接参数客户端的可选范围很广我从三个方向说说。TigerVNC Viewer 是配套客户端跨平台界面朴素但稳定连接时填IP:端口注意这里填的是端口号不是会话编号192.168.1.10:5901才对填成:1会连不上。RealVNC Viewer 的观感更现代一些缩放和画质调节做得比较细用起来挺舒服。体积小、免安装的还有 TightVNC 的客户端随手一拷就能用。连接时几个参数值得留意Quality和Compression这两档画质调高、压缩调低局域网里画面更细腻但吃带宽跨网络时反过来牺牲一点画质换流畅度。Scaling用来缩放画面屏幕小的时候把远程 1080p 缩到窗口里比来回拖滚动条舒服。至于View only模式勾上之后你就只能看不能动演示给别人看的时候很实用顺便也避免了误操作。5.2 剪贴板、中文输入法与字体这三样直接影响你用 VNC 干活的舒适度值得单独调。剪贴板前面提过靠 xstartup 里的vncconfig -iconic 解决双向同步。如果发现只能单向或者干脆不动检查一下这个进程有没有真正跑起来另外客户端里也有专门的剪贴板选项两边都确认一遍。中文输入法是刚需。远程会话里的输入法要单独拉起因为它的环境变量没继承你物理登录的那套。以 fcitx 为例在 xstartup 里补上export GTK_IM_MODULEfcitx export QT_IM_MODULEfcitx export XMODIFIERSimfcitx fcitx -d 输入法本身要先在系统里装好比如sudo apt install -y fcitx fcitx-googlepinyin然后重新启动 VNC 会话让新配置生效。用 ibus 的话换成ibus-daemon -drx 并把环境变量改成 ibus 即可。这一步做完远程里就能正常打中文了。字体这块如果你主要在远程终端里敲代码一套清晰的等宽字体能明显减轻眼睛负担。系统里装好常用字体包sudo apt install -y fonts-noto-cjk fonts-firacode然后在终端软件里把字体设成 Fira Code、JetBrains Mono 这类中英文混排下字符宽度对齐更整齐长时间看代码的体验提升肉眼可见。这个属于锦上添花但调过一次就回不去了。5.3 非局域网访问的安全做法前面多次提到 SSH 隧道这里把具体做法补全。原理是让 SSH 先把一条加密通道建好VNC 流量塞进这条通道里走这样即使中途被人截获看到的也是加密后的内容。在客户端机器上执行ssh -L 5901:localhost:5901 -N -f user服务器IP这条命令的意思是把本地 5901 端口的流量转给服务器本机能访问到的 5901。执行后没有明显输出是正常的它是静默在后台挂着。然后在 VNC 客户端里连localhost:5901实际连到的就是远程的 VNC 服务全程走加密通道。配合这个方案服务端的~/.vnc/config里设localhostyes更稳妥VNC 端口根本不对外暴露攻击面小很多。用完之后断开隧道杀掉那个后台 SSH 进程就行可以用ps找到再kill或者干脆关掉终端重开。6. 备选方案x11vnc 共享现有桌面6.1 两种方案的取舍如果需求不是给我开一块新桌面而是把我眼前这块物理桌面推给别人看那 x11vnc 更对口。它抓的是已经开着的那块屏所以你在物理机上的操作对方能实时看到适合远程协助和演示。判断标准很简单要独立的工作空间选 TigerVNC 独立会话要共享现有画面选 x11vnc。两者也可以并存互不冲突按需启用。6.2 一条命令拉起服务先装sudo apt install -y x11vnc设一个密码文件x11vnc -storepasswd默认写到家目录的.vnc/passwd。然后拉起服务x11vnc -auth guess -display :0 -forever -shared -rfbauth ~/.vnc/passwd -rfbport 5900 -noxdamage -repeat参数里-display :0指向物理桌面-forever让它在客户端断开后继续挂着-shared允许多人同时连-rfbauth指定密码文件-rfbport是端口。这命令跑起来它就在前台盯着想后台跑加-bg或者同样塞进 systemd。这里再强调一次前面说过的坑如果当前是 Wayland 会话x11vnc 抓到的基本是黑屏。先按 2.1 节把会话切回 Xorg 再试。7. 常见问题排查速查7.1 画面类问题黑屏、灰屏、花屏黑屏和灰屏几乎占了 VNC 问题的一大半原因基本都在 xstartup 和会话类型上。下面这张表是我整理的高频对照遇到问题先按这个顺序排查。现象可能原因排查动作纯黑屏鼠标也不动会话是 Wayland 或 xstartup 未执行确认$XDG_SESSION_TYPE为 x11检查 xstartup 是否有执行权限灰底加一个 X 光标xstartup 里没有正确拉起桌面检查gnome-session那几行确认环境变量已 unset只有壁纸没有图标和任务栏桌面组件没启动换用 xfce4 的 xstartup或补齐 gnome 相关组件画面出现彩色花块色深或驱动问题把depth降到 24更新显卡相关依赖连上后一段时间变黑屏保或省电策略触发在会话里关闭息屏或调整电源设置排查时永远先看~/.vnc/下的日志它比任何猜测都可靠。7.2 连接类问题拒绝连接与认证失败连接被拒绝第一反应是服务压根没起来。用vncserver -list看会话在不在再用sudo systemctl status vncserver:1.service看服务状态。如果服务在跑还连不上检查监听地址和端口ss -tlnp | grep 5901能看到监听记录才说明服务真的在等连接。连接不上常见于防火墙拦了端口或者~/.vnc/config里localhost设成了yes那外部自然连不进来。认证失败有两种。一种是密码错注意vncpasswd只取前 8 位这个特性很可能你输的长密码被截断了。另一种是客户端缓存了旧密码RealVNC Viewer 这类客户端的密码管理器里存着上一次的凭据删掉重新输一次就好。7.3 交互类问题键盘鼠标与声音鼠标能动人但点击没反应多半是权限或者会话卡死重启会话一般能解决。键盘输入错乱、快捷键被本地客户端截走需要在客户端里关掉捕获快捷键之类的选项或者改成用CtrlAltShift组合。至于声音VNC 默认不带得配 PulseAudio 转发命令不短、依赖也多我个人的判断是远程改代码基本用不上声音不值得为它增加配置复杂度除非你就是要在远程里看视频那就另说了。8. 我实际用下来的几点体会写到最后分享几条不在任何官方文档里、但确实能帮你省时间的经验。装之前先把这台机器到底要给谁用、从哪儿连过来想清楚比装完再返工改配置轻松得多。VNC 密码的 8 位限制、xstartup 的执行权限、SESSION_MANAGER这两个变量要 unset、Wayland 下 x11vnc 会黑屏这四个点是我这些年见过最多的翻车原因基本每次帮人配都会遇到其中一个。还有一个我自己的习惯装完第一个能连的会话之后立刻在物理机上用同样的会话配置再开一个:2确认多会话共存没问题。因为独立会话这种能力在真正需要的时候现配往往来不及提前验证一遍心里有底。如果你是给学生或同事搭共享的开发环境记得每个人用自己的账号跑自己的 VNC 会话别所有人都往同一个会话里连那样会互相抢鼠标、互相覆盖窗口用起来非常难受。每人一个会话编号、各用各的密码这才是正确的用法。这些细节我踩过一次就记住了希望你不用再踩。