
1. 花屏问题定位先判断是哪一环节出了毛病先说结论在无显示器环境下用 x11vnc 连麒麟 2403出现花屏、色块、红蓝颜色颠倒甚至刷新残影十有八九不是 x11vnc 本身的问题而是 Xorg 在“没有物理显示器”时拿不到正确的显示参数导致整个图形栈从帧缓冲格式到颜色深度都处于一种拧巴的状态。你远程看到的那些色块其实是 X server 内部 framebuffer 里的“脏数据”被 VNC 抓出来后的直观表现。我见过不少同事第一反应是换 VNC 客户端从 TigerVNC 换到 RealVNC 再换到 VNC Viewer折腾一圈色块还在。也有人怀疑是网速问题把画质调到最低结果满屏马赛克更严重。这些方向都偏了。判断问题环节其实很简单花屏只出现在远程画面里本地接上显示器看是正常的那就是“采集/编码/传输”链路的问题如果本地接显示器也花那就是显卡驱动或显存问题。无显示器环境下绝大多数属于前一种。更准确点说是 Xorg 在没有连接显示器时输出分辨率、像素格式、刷新率三项参数都无法从 EDID 中读取只能靠默认值或驱动猜测猜错了就花。还有个更隐蔽的情况。有些工控机用的是国产显卡或集成显卡驱动在 headless 状态下根本不初始化加速模块Xorg 回落到 modedestting 或 framebuffer 驱动颜色深度变成 16 位甚至 8 位。x11vnc 默认会尝试用“最优视觉”方式抓屏抓到 PseudoColor 或 DirectColor 这种非常规 visual送到支持 TrueColor 的 VNC 客户端里自然就颜色错乱、出现彩色噪块。1.1 无显示器共有的三类故障特征我把实际遇到的“无显示器花屏”归纳成三类读者可以直接对照自己的现象快速归类。第一类是整屏色块、颜色明显失真。比如蓝色变橙色、红色变绿色或者屏幕像曝光过度的老照片这种通常是像素格式pixel format不匹配。Xorg 侧 framebuffer 是 BGR 排列x11vnc 或客户端按 RGB 解析通道就串了。也有一部分是 Xorg 落到了低色彩深度模式客户端还在按 24 位解析高字节全被吃掉。第二类是局部区域出现彩色噪点、细碎色块而且往往在你拖动窗口、刷新页面、图形内容变化时才出现静止画面过几秒又会自己“恢复”。这种大多跟硬件加速有关。GPU 加速渲染时把内容画到了某个显存缓冲区但无显示器环境下 x11vnc 抓屏用的是 SHM 共享内存方式XGetImage抓到的是前台缓冲区的数据两者不同步抓到一半就拉垮了。第三类是分辨率不对导致的“显示不全花边”比如实际 VNC 画面停在 640x480但桌面程序界面是按 1920x1080 画的大量窗口在屏幕外或叠加在一起刷新时互相覆盖形成类似花屏的混乱画面。这种情况下你切到命令行执行 xrandr 看输出多半只有一行 trident 都会报错。1.2 用 Xorg.0.log 快速锁定驱动和显示输出状态不要凭感觉猜无显示器环境下系统里最有价值的第一手资料是 /var/log/Xorg.0.log。在麒麟 2403 上Xorg 日志通常也是这个路径如果启用了多用户或多次 startx 会有 Xorg.0.log.old以最新那个为准。重点看三块内容。第一块是驱动加载段搜索 “(II) LoadModule 和 (II) Using input driver” 附近确认加载的显卡驱动是 modesetting、fbdev 还是厂商私有驱动比如 nouveau、radeon、amdgpux。第二块是屏幕输出检测段搜索 EDID 和 Monitor 关键字。有物理显示器时会看到 “EDID for output HDMI-1” 一段很长的十六进制数据无显示器时通常只有一行 ”(II) HDMI-1: disconnected” 或者直接缺失。第三块是颜色深度和 framebuffer 信息搜索 “Depth” 和 “Visuals”无显示器环境如果出现 Depth 16 或 Depth 8基本可以直接判定花屏根源。我自己的排查习惯是先把日志只过滤出错误和警告grep -E (EE)|(WW) /var/log/Xorg.0.log | head -n 30无显示器环境下最常见的两个警告就是 “no EDID data available” 和 “No physical display connected, falling back to default mode”。看到这两个警告就可以直接进入下一步配置虚拟显示器。1.3 一个有用的类比为什么“普通游戏没事虚幻引擎就花”网上有人反馈麒麟系统跑普通游戏没问题一跑虚幻引擎的游戏就花屏闪退。这个现象和无显示器环境花屏有很强的类比价值。普通游戏画面变化小、颜色简单、帧率低即使 Xorg 的像素格式有点别扭VNC 客户端用宽松的容错也能扛过去。但虚幻引擎这种重负载 3D 渲染场景每帧都有大量渐变、透明混合和高速变化颜色精度要求极高稍有格式错位就会在渐变区域拉出色带在高速刷新区域产生撕裂和色块。无显示器环境也一样。桌面静止时你看看不出毛病一旦打开浏览器滚动页面、播放视频、或者跑一个带图表的监控程序就开始疯狂刷新色块。本质都是同一个问题像素数据在 X 帧缓冲和 VNC 编码器之间做了不兼容的转换平时低复杂度画面掩盖了问题高复杂度画面一压就爆。2. 让 Xorg 以为有显示器虚拟显示器与分辨率修正要根治无显示器环境的花屏核心思路不是去调 VNC 客户端而是让 Xorg 正常起来。Xorg 拿不到 EDID我们就“骗”它要么在配置层面给一个虚拟的显示器参数要么用硬件 EDID 模拟器物理伪造一个。两者我都试过分别适合不同场景。先说适用性判断。如果你面对的工控机是现场设备不方便拆机箱也没有空闲的 HDMI 接口可插那就用纯软件方案写 xorg.conf 或改内核启动参数。如果你有操作条件且手头有十几块钱的 HDMI 假负载EDID 模拟器那我强烈建议直接用硬件这是最稳的办法没有之一。2.1 通过 xorg.conf 配置虚拟 Monitor在麒麟 2403 上Xorg 的配置文件在 /etc/X11/xorg.conf如果不存在就自己建一个。核心思路是给每个输出端口定义一段虚拟的 Monitor 配置直接把分辨率、刷新率写死让 Xorg 不需要读 EDID 也能按预设值启动。我在实际项目里用的是一份针对 1920x1080 的配置sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.bak sudo vim /etc/X11/xorg.conf写入如下内容Section Monitor Identifier VNC-Monitor-0 VendorName Virtual ModelName Virtual Display Option DPMS false Modeline 1920x1080_60.00 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync vsync Option PreferredMode 1920x1080_60.00 EndSection Section Device Identifier Card0 Driver modesetting Option PrimaryGPU true Option SWcursor true EndSection Section Screen Identifier Screen0 Device Card0 Monitor VNC-Monitor-0 DefaultDepth 24 SubSection Display Depth 24 Modes 1920x1080_60.00 Virtual 1920 1080 EndSubSection EndSection解释几个关键点。Modeline 那一长串数字是像素时钟和时序参数不是随便抄的它是标准 CVT 时序下 1920x108060Hz 的常规值。如果懒得记可以用命令生成cvt 1920 1080 60然后在 Modeline 那一行填生成的完整数据。对于分辨率要求不高的工控机1680x1050 或 1366x768 也完全可以时序参数对应调整即可。Screen 段里的 DefaultDepth 24 特别重要。无显示器环境容易落到 16 位色深这里直接锁死 24 位能从根源上避免一部分颜色错乱。Virtual 1920 1080 是给 X server 的虚拟帧缓冲大小它决定了逻辑桌面的尺寸也控制着 x11vnc 能抓到的画面范围。配置写好后重启图形服务sudo systemctl restart display-manager注意麒麟桌面版可能用的是 lightdm 或 gdm3重启前先确认一下当前 display-manager 是哪个避免重启了没反应。重启后再执行xrandr正常情况下会列出你的虚拟分辨率和刷新率。如果看到的是 1280x1024 或 1024x768那说明 Modeline 设置没生效或者驱动没有按帧配置文件加载。这时候可以用 2.2 节的方式手动修正。2.2 xrandr 动态修正分辨率和主输出xorg.conf 方案适合开机就要干净环境的场景但调试阶段或者配置没生效时我现在更习惯用 xrandr 在运行态直接改。xrandr 是 X 自带的命令行工具在无显示器环境的调试几乎离不开它。先看当前输出状态xrandr --verbose无显示器环境下输出列表里每个接口都可能是 disconnected 状态但 VNC 访问时我们需要的是让某个接口强制“在线”。用 --auto 让它自动探测可能没用因为探测不到 EDID。更靠谱的是手动指定模式xrandr --output HDMI-1 --mode 1920x1080_60.00 --primary --rate 60.00 --pos 0x0如果你不确定接口名可以先 xrandr 看列表。麒麟下常见的是 HDMI-1、VGA-1、DP-1。有些国产主板只有一个输出口就正常按这个思路来。注意xrandr 直接指定模式的前提是 X 已经加载了我们刚才定义的 Modeline。如果 Modeline 没有预定义会报 “cannot find mode” 的错误。所以最稳妥的顺序还是xorg.conf 定义 Modeline启动后用 xrandr 修正主输出。实际使用中我发现一个问题xrandr 在无显示器环境下设置的分辨率一旦 X server 因为崩溃或重启而重新加载就会还原成默认值。所以把 xrandr 命令写成一个开机自启脚本比较合理比如放到 /etc/rc.local 或 systemd service 里。我这里用 systemd 管理简单排队一次sudo vim /etc/systemd/system/fix-screen.service内容[Unit] DescriptionFix resolution for headless system Afterdisplay-manager.service [Service] Typeoneshot ExecStart/usr/bin/xrandr --output HDMI-1 --mode 1920x1080_60.00 --primary --rate 60.00 --pos 0x0 Userroot [Install] WantedBymulti-user.target然后sudo systemctl enable fix-screen.service sudo systemctl start fix-screen.service2.3 硬件 EDID 模拟器是最省事的兜底如果你不想折腾 xorg.conf或者厂商驱动对虚拟 Monitor 的兼容性差花十几块钱买个 HDMI/DVI EDID 模拟器插到工控机的视频输出口上问题直接消失大半。它本质上是一个小芯片给显卡回传一个标准分辨率的 EDID 数据让显卡以为接了一台真实的显示器。这个方案我是在一台老旧的集成显卡工控机上验证的。那台机器无论如何配置 xorg.conf驱动都会自己检测显示器并强制回退到低分辨率用软件办法怎么也压不住。插上 EDID 模拟器后开机直接 1920x1080VNC 画面干净利落连 x11vnc 参数都不用调。当然也有缺点需要额外硬件、占用一个物理输出口。但对现场设备来说只要机箱能塞得进这几十块钱的成本换回来的稳定性和时间成本非常划算。很多长期无人值守的工控机我都建议直接插一个省心。3. x11vnc 参数调整颜色格式、抓屏与编码的实操解决完 Xorg 侧的输出问题花屏大概率已经消失了七成。剩下三成需要靠 x11vnc 参数兜底。这套东西我平时虽然用得多但也是踩过坑才把参数吃透。先说一个很多人忽略的事实x11vnc 本身不是一个 VNC server它更准确的身份是“X 帧缓冲的转码器”负责把 X server 的输出转成 VNC 协议的数据包。所以它对像素格式的解读和转换极其挑剔。默认情况下它会尝试使用 X server 的 native visual 和 pixel format这在无显示器环境经常出问题。3.1 最关键的两个参数-visual 与 -pixelformat这两个参数是处理花屏的第一道武器也是最容易被忽略的。-visual TrueColor强制 x11vnc 以 TrueColor 视觉方式抓取避免 PseudoColor 或 16 位色深下的颜色失真。无显示器环境下 X server 如果默认 depth 是 24通常已经是 TrueColor但有些驱动或配置会改变它加这个参数能保证一致性。-pixelformat控制 X 帧缓冲到 VNC 协议传输时的像素格式。默认 x11vnc 会根据客户端协商结果使用 RGB888但麒麟无显示器环境下 framebuffer 可能是 BGR 排列导致红蓝互换。强制指定 BGR 排列即可x11vnc -visual TrueColor -pixelformat bgr888如果你用 VNC Viewer 这类客户端连上去发现颜色还是怪怪的可以反向试 rgb888。判断标准很简单看红色元素是否显示成蓝色如果是就是 RGB/BGR 通道序反了。看到这儿可能有读者会问为什么默认情况不自动适配因为 X server 上运行的图形程序Qt、GTK、Electron 等写入 framebuffer 时的字节顺序不完全一致尤其是无显示器环境下驱动经常不会主动报告正确的格式x11vnc 只能盲目猜测。3.2 减少刷新闪烁的辅助参数花屏还有一类表现是“刷新残影”就是拖动窗口或鼠标时画面出现一列列残影像屏幕没擦干净。这个跟像素格式关系不大而是 x11vnc 抓屏和客户端刷新机制的问题。我常用的几个参数x11vnc -ncache 10 -ncache_cr -wireframe -solid-ncache 10会启用客户端缓存把屏幕分隔成的多个小区域尝试增量缓存大幅减少刷新时的闪烁和残影。-ncache_cr是配合客户端支持的 CopyRect 指令优化。-wireframe让窗口拖动时只显示线框而不是完整画面减少编码压力。-solid我理解是一个比较冷门的参数它会在没有窗口活动时用纯色刷新屏幕背景减少 VNC 数据量看起来也更干净。另外-fixscreen V1值得注意。无显示器环境下分辨率变化是家常便饭比如某个程序主动把分辨率从 1920x1080 改成 1600x900很多 VNC 客户端会直接花掉。-fixscreen V1让 x11vnc 在检测到分辨率变化时自动重新调整抓屏参数避免客户端因为分辨率不匹配而花屏。启动命令结合后台守护我一般写成x11vnc -forever -shared -rfbauth /etc/x11vnc.pass \ -rfbport 5900 -display :0 \ -visual TrueColor -pixelformat bgr888 \ -ncache 10 -ncache_cr -wireframe -solid \ -fixscreen V1 -speeds modem-speeds modem是我个人习惯它让 x11vnc 在低速网络下主动降低扫描频率减少 VNC 数据量。对广域网远程访问有真实帮助局域网无所谓。3.3 完整启停脚本实例放在 systemd 里更省事创建 /etc/systemd/system/x11vnc.service[Unit] Descriptionx11vnc remote access Afterdisplay-manager.service network-online.target [Service] Typesimple ExecStart/usr/bin/x11vnc -forever -shared -rfbauth /etc/x11vnc.pass \ -rfbport 5900 -display :0 \ -visual TrueColor -pixelformat bgr888 \ -ncache 10 -ncache_cr -wireframe -solid \ -fixscreen V1 -speeds modem Restarton-failure RestartSec5 [Install] WantedBymulti-user.target设置密码文件sudo x11vnc -storepasswd yourpassword /etc/x11vnc.pass chmod 600 /etc/x11vnc.pass启用并启动sudo systemctl enable x11vnc.service sudo systemctl start x11vnc.service这套配置用下来多数花屏问题都能解决。4. 备选思路Xvfb 虚拟帧缓冲和 xrdp 绕行方案如果前面两个方案的配置始终无法稳定生效或者你不想碰 Xorg 的配置文件那可以走绕行方案。两个方向用 Xvfb 建立完全独立的虚拟帧缓冲或者干脆不用 Xorgx11vnc改用 RDP 协议的 xrdp。4.1 Xvfb x11vnc 适合什么场景XvfbX Virtual Framebuffer是 X server 的内存版本它不依赖任何物理显示器或显卡直接在内存里画出一块虚拟屏幕。这对无显示器工控机来说是最“干净”的图形环境因为它根本不需要去适配 EDID、分辨率、驱动这些乱七八糟的东西。适合的场景很明确工控机上跑的是纯运维类应用比如 OpenSCADA、组态软件、Web 界面不需要硬件 GPU 加速。Xvfb 天然规避了显卡驱动在 headless 下的各种幺蛾子。启动方式Xvfb :1 -screen 0 1920x1080x24 export DISPLAY:1 x11vnc -display :1 -forever -shared -rfbauth /etc/x11vnc.pass \ -rfbport 5901 -visual TrueColor -ncache 10注意端口改成了 5901避免和原有 x11vnc 冲突。但你如果完全不依赖物理显示器可以直接把图形服务整体切到 Xvfb这样 Xorg 的问题就完全不存在了。Xvfb 的缺点是应用无法使用硬件加速3D 渲染和多视频流场景会吃力。如果你的场景需要跑复杂图形界面Xvfb 会拖后腿。另一个缺点是脱离 Xorg 后桌面环境如 UKUI、KDE和某些需要访问 DBus/显示服务的国产软件可能会行为异常需要额外验证。4.2 国产麒麟上用 xrdp 的适配情况xrdp 走 RDP 协议它对无显示器环境的处理逻辑和 VNC 完全不同。xrdp 本质上也是先建立一个虚拟的 X session通过 Xorg 的 dummy 驱动或 Xvfb再通过 RDP 协议传输。但它对分辨率变化、颜色格式的容错比 x11vnc 好很多因为 RDP 协议的帧缓冲设计本身就考虑到了各种像素格式差异。麒麟 2403 上安装 xrdpsudo apt install xrdp sudo systemctl enable xrdp sudo systemctl start xrdp然后用任意 RDP 客户端Windows 自带远程桌面连接或跨平台的 Remmina连工控机 IP 的 3389 端口。实测下来如果只是做桌面运维和软件配置xrdp 比 x11vnc 稳定得多尤其颜色保真度让人省心。不过 xrdp 也有它自己的毛病对国产桌面环境UKUI的会话启动脚本兼容性偶尔有问题经常需要手动编辑 /etc/xrdp/startwm.sh 指定会话类型。还有个常见坑是 xrdp 默认监听的 3389 端口和 Windows 自带远程桌面默认端口一样如果网内有两台机器同时用 RDP端口冲突要提前规划。到底是 VNC 还是 RDP我的判断标准很简单如果应用必须在原有桌面会话里长期运行比如仪表盘大屏、组态软件持续显示优先保 x11vnc 方案如果是临时运维、改配置、装软件直接 xrdp省心。5. 常见问题速查与独家排障经验5.1 一张表对照现象、原因和操作故障现象最可能的根源优先处理动作整屏红蓝互换、颜色错乱帧缓冲 RGB/BGR 通道序反x11vnc 加 -pixelformat bgr888 或 rgb888 反向试局部彩色噪点、细碎色块GPU 加速与 VNC 抓屏不同步强制软件渲染或 xorg.conf 里加 SWcursor 和加速关闭参数分辨率不对、画面显示不全无 EDID 导致 Xorg 回退默认模式配置虚拟 Monitor Modeline或插 HDMI 欺骗器静止正常、刷新就花色彩深度降到 16 位/8 位DefaultDepth 强制 24x11vnc 加 -visual TrueColor拖动窗口有残影编码器扫描与帧刷新竞争加 -ncache 10 -wireframe -solid分辨率变化后整屏花掉X server 分辨率被应用改了加 -fixscreen V1 自动重抓屏颜色渐变区域出现色带8 位/16 位伪影常见于复杂渲染强制 24 位色深 TrueColor5.2 强制软件渲染在无显示器工控机上的作用前面提到过一个重要的独家经验无显示器环境下如果花屏跟 GPU 加速紧密相关——比如桌面静止没事一播放视频、打开大型图表就花——那就别执着于驱动调优了直接强制软件渲染往往能四两拨千斤。做法是把环境变量写进 /etc/environmentecho LIBGL_ALWAYS_SOFTWARE1 | sudo tee -a /etc/environment echo GALLIUM_DRIVERllvmpipe | sudo tee -a /etc/environmentLIBGL_ALWAYS_SOFTWARE1 强制 OpenGL 走 Mesa 软件实现llvmpipe绕开 GPU 加速在 headless 下的不稳定路径。缺点自然是 3D 性能下降但工控机跑的大多是 2D 应用、仪表盘、网页、简单图表软件渲染完全够用。我在一台集成显卡工控机上验证过上了这个环境变量后VNC 里播放视频从满屏噪块变成正常画面CPU 占用增加约 10%完全可接受。5.3 几个容易踩的坑第一个坑是桌面会话和 Xvfb 会话混用。如果你把 DISPLAY 环境变量改了客户端连接的又是原来的 :0 会话应用的窗口会跑到别的 display 上x11vnc 自然抓不到内容。排查时先确认自己连的是哪个 display。第二个坑是 x11vnc 密码文件权限。很多人在第一版启动脚本里忘了 chmod 600x11vnc 会直接拒绝启动日志显示 permission denied。看似小问题现场排查时特别容易泄气。第三个坑是防火墙。麒麟系统如果没有主动开 ssh 端口VNC 的 5900/5901 端口在防火墙里也不通客户端会一直转圈然后报“连接超时”。先确认sudo ufw status sudo ufw allow 5900/tcp第四个坑是 systemd 服务的启动顺序。Xorg 如果还没完全起来x11vnc 连不上 display启动脚本直接失败退出。虽然 service 配置了 Restarton-failure但很多人没加 RestartSec5 或没在 After 里声明 display-manager导致每次开机都要手动启动一次。这问题在我刚用 systemd 管理 x11vnc 时出现过后来加了 After 依赖和 RestartSec 才消停。第五个坑是关于国产软件的“A卡”特效。麒麟自带的 UKUI 桌面在某些版本里默认开启窗口动画和混合特效compton/picocom。这些特效在无显示器环境加 VNC 时经常导致截图延迟、色块残留。如果排查到这一步仍然找不到原因可以把窗口特效关闭试试我在麒麟 2403 上遇到过类似问题关闭特效后立刻干净了。操作方式打开“设置-个性化-窗口管理器-特效”关掉。命令行的方式可以查一下 compton/picocom 进程杀干净即可。6. 说点实在的这套方案我前后折腾了差不多一周从最初怀疑 x11vnc 编码器到后来发现是 Xorg 无 EDID 导致的颜色深度问题中间走了不少弯路。现在总结出来其实就两条主线第一优先解决 Xorg 侧的输出正确性包括虚拟 Monitor、Modeline、DefaultDepth 24第二用 x11vnc 参数兜住像素格式和编码的边角-visual TrueColor 和 -pixelformat bgr888 是核心。工具选型上如果你的环境允许插硬件HDMI EDID 模拟器是零成本换来最稳定的方式。不能插硬件就按上面 xorg.conf xrandr 的组合配置也能覆盖绝大部分场景。xrdp 适合临时运维不建议作为长期桌面服务的主力因为麒麟上 UKUI 会话的兼容性还需要时间打磨。最后分享一个很小的细节排查花屏时顺手把客户端也换一换。同一个 x11vnc 服务下VNC Viewer 显示正常而 TightVNC 客户端花屏这种情况真实存在因为客户端端对像素格式的支持程度不一样。遇到问题时先在两端交叉测试能帮你快速缩小问题范围省下不少排查时间。