如果你把一台装好银河麒麟2403的mini主机丢进机柜、关掉显示器、只靠SSH和远程桌面去管理它,那么“无显示器开机后x11vnc画面花屏”这件事,大概率会折磨你至少一个晚上。我的真实经历是:机器放在角落,意外断电再上电后,VNC画面全是彩色条纹和马赛克色块,像显卡烧了一样。第一反应当然是重装桌面,UKUI卸了装、装了卸,问题一点没变。后来我静下来翻了日志才发现,花屏根子根本不在桌面,而在“无显示器开机时,X服务器拿着错误的分辨率和色深启动,x11vnc只是把这份错误原样推给了我的屏幕”。这篇文章把我当时的排查过程和最终方案完整写出来,给同样在做麒麟无头远程桌面的朋友一个参考,别再动辄重装。
1. 无头开机花屏的现象复盘:为何第一反应是重装桌面
1.1 现场环境与最初的想当然
先说清楚环境。我用的是一台老式mini主机,配置不高,装的是银河麒麟桌面操作系统V10的2403版本,桌面环境是系统自带的UKUI。平时这台机器不接显示器,通过SSH做管理,需要图形界面操作的时候就用x11vnc开5900端口远程连进去。跑了一个多月一直挺稳,结果某次机房断电重启之后,VNC连进去的画面就彻底不对劲了。
当时看到的画面非常典型:远程桌面上布满横向或斜向的彩色条纹,窗口轮廓能看见一部分,但大面积颜色错乱,有些区域干脆是灰白噪点一样的色块。鼠标还能移动,点关闭按钮偶尔能点中,但整体几乎不可用。
因为不懂前因后果,我的第一反应就是桌面环境坏了,可能是某次意外断电导致UKUI的配置损坏。于是我做了一个后来想想非常浪费时间的事情——反复重装桌面。sudo apt remove ukui-desktop清掉,再sudo apt install ukui-desktop装回来,中间还试过重装lightdm、重置用户目录下的.config缓存。结果都一样:重启以后连VNC,照样花屏。
1.2 花屏的真实观感:不是“全黑”也不是“碎裂”
这里需要把花屏的形态讲细一点,因为同样是“花屏”,根因可能完全不一样。我这个是典型的“颜色映射错乱”:分辨率看起来还在,窗口布局也没有跑飞,但色彩完全不对。有些区域像16位色被强行压成8位色之后出现的色带,有些区域像D-Sub接口接触不良时的那种斜纹雪花。
最诡异的是,某些操作能让画面瞬间恢复正常几秒钟,比如在VNC客户端里切换一下色彩编码、或者触发一次全屏重绘,画面会短暂地“正常”一下,然后随着鼠标移动或者窗口刷新又开始花。这个细节对后来定位问题很重要:它说明系统本身没有完全崩溃,只是某些底层参数从启动那刻起就是错的,任何一次局部刷新都会把错误重新暴露出来。
1.3 为什么重装桌面是无效动作
后来我意识到一个基本逻辑问题:重装桌面动的是应用层组件,而花屏发生在X显示服务器初始化阶段。可以这样理解:Xorg相当于一栋楼的地基和框架,UKUI桌面只是里面的家具和软装。地基盖歪了,你换再多的家具,墙照样是斜的。
麒麟2403默认引导到图形界面时,显示服务器会去枚举显卡输出、显示器EDID、可用分辨率和色深。在没有物理显示器的场景下,这些信息全是缺失或异常的。Xorg如果拿着异常参数启动了,那么后面所有通过frameruffer呈现的内容,包括x11vnc抓屏、桌面合成器、窗口渲染,都会继承这套错误参数。重装桌面根本碰不到这一层,自然无效。
2. 根因拆解:EDID缺失与X服务器默认参数
2.1 显卡为什么需要显示器“自我介绍”
要弄清楚花屏,必须先了解EDID。EDID全称是Extended Display Identification Data,你可以把它理解成显示器递给显卡的一张“名片”。这张名片上写着显示器厂家、尺寸、支持的分辨率列表、刷新率范围、色深、像素时钟等信息。
正常插着显示器的时候,显卡通过DDC通道读取这张名片,然后按名片上的参数去驱动屏幕。无显示器开机时,这张名片根本不存在。保守的显卡驱动会选一组最安全的“兜底参数”去启动X服务。问题就出在,这个兜底参数在麒麟2403上经常不是我们想要的那个。
2.2 麒麟2403拿不到EDID时的“默认三件套”
我在日志和实测中看到的典型默认行为有三个:
- 默认分辨率被降到800x600甚至640x480,刷新率显示为0Hz或者异常值
- 色深可能被压到16位色,极端情况下甚至用8位伪彩色模式
- 多个显示输出(HDMI、VGA、DP)同时被枚举为“连接的”,且分辨率冲突
无显示器时执行xrandr,经常能看到类似下面的输出:
Screen 0: minimum 320 x 200, current 800 x 600, maximum 8192 x 8192 HDMI-1 connected 800x600+0+0 (normal left inverted right x axis y axis) 0mm x 0mm 800x600 59.86 + 640x480 59.94注意这里的“connected”很具有欺骗性,它并不代表真的接了显示器,只是驱动认为这个输出端口可能存在设备。而分辨率只有800x600这一档可用,色深在日志里也可能不是24位。
2.3 x11vnc为什么“忠实呈灾”
x11vnc的工作原理是从X服务器的framebuffer(帧缓冲区)里直接读取当前屏幕内容,然后编码成RFB协议发给VNC客户端。它就像一台摄像机对着X Server的“最终画面”拍,X画面本身是花的,它拍下来自然也是花的。
很多人遇到花屏第一反应是调x11vnc参数,比如换tight编码、调低quality、关掉JPEG压缩。我当初也试过,结论是这些参数改变的是“编码过程”,而不是“画面内容本身”。这就好比你的摄像机镜头前放了一块裂缝的玻璃,你调摄像机的白平衡、分辨率、码率都没用,因为问题出在拍摄对象那一边。
真正需要修的是X framebuffer本身的分辨率和色深,而不是x11vnc的编码方式。
3. 五步排查链路:从Xorg日志到xrandr,一步步拿证据
3.1 先分清是本地花屏还是远程花屏
排查的第一步,是确认花屏是否只出现在VNC远程画面里。我找了一台带VGA输入的旧显示器,把主机接上去直接开机。结果本地显示器同样花屏,只不过因为本地显示器的EDID能被读取,花屏程度轻一点,但色彩依然不正常。这说明问题至少在显示服务层,不在VNC传输层。
如果你本地正常、只有VNC花,那方向会不一样,更多要考虑x11vnc抓屏参数。但在我这个场景里,本地都花,焦点就必须转向X服务器本身。
3.2 grep Xorg.0.log,重点看这三段
麒麟2403的Xorg日志默认在/var/log/Xorg.0.log。我用grep过滤出关键信息:
sudo grep -Ei "edid|screen|depth|fbbpp" /var/log/Xorg.0.log日志里比较值得注意的有两处。第一处是EDID相关的行,通常显示类似No EDID has been found或者Unable to fetch EDID。第二处是关于屏幕初始化的部分,写着Screen 0: ...以及Depth参数。我的环境里明确显示Depth 16、fbbpp 16,看到这行的时候我心里已经明白了一大半。
色深16位意味着每个像素只有2字节,绿色通道少2位、蓝色通道少2位,颜色量化出现明显误差。这种模式下,渐变背景和图片会呈现明显色带,某些颜色组合会被映射成完全错误的色块,观感就是“花屏”。
3.3 用xrandr看“显示器明明不存在,系统却假装有”
在图形会话里开一个终端跑xrandr,可以看到输出端口的状态。无显示器场景下,有用的信息是“当前分辨率”和“可用分辨率列表”。如果可用分辨率里只有640x480、800x600这种老掉牙的档位,那说明显卡没有拿到任何EDID提供的有效模式。
还有一种情况是多输出端口互相打架。我见过一台机器同时把HDMI-1和VGA-1都标记为 connected,但各自的分辨率冲突,导致Xorg在启动时选择了一个两边都不讨好的中间值。这种冲突在无头服务器上比想象中常见,尤其是老主板加转接线组合。
3.4 排除VNC Viewer侧的解码问题
为了确保花屏不是因为我的VNC客户端解码器有问题,我用几个不同客户端做过对照:
- Remmina默认的VNC协议连接
- 手机端bVNC连接
- 用
x11vnc -ncache 0关闭服务端缓存后重连
三个客户端表现完全一致,花屏形态一样。这就排除了本地播放器解码兼容性的嫌疑。我也试过在VNC连接里把色彩设置为24bit真彩,依然无效,因为服务端framebuffer本身就只有16bit数据,客户端再怎么要求高色深也没有用。
3.5 临时指定分辨率验证假设
到了这一步,我基本锁定是无显示器启动导致分辨率、色深异常。为了验证这个判断,我临时用命令行强制指定分辨率。具体做法是先切到文本终端,杀掉当前的Xorg会话,然后用带参数的启动方式拉起来:
sudo systemctl isolate multi-user.target sudo startx -- -depth 24或者更直接一点,在Xorg配置里临时固定深度。startx起来后我再跑xrandr,分辨率依然受限于可用模式列表,但色深已经变成24位,VNC画面里那种大面积的色带和斜纹明显减轻。这基本坐实了“色深错乱贡献了至少一半的花屏症状”。
4. 解决方案落地:虚拟显示器与Xorg dummy 配置
4.1 硬件方案:HDMI虚拟插头,20元买个省心
最省事的办法其实是物理层面的,买一个HDMI/DP的虚拟显示器插头,大概十几二十块钱。这个东西内部集成了一颗EDID芯片,插到显卡接口上之后,显卡会认为你接了一台真实存在的1080p显示器。
我实测下来,插上这个虚拟头之后,系统不用做任何配置,开机自动识别1920x1080,色深恢复24位,xrandr里能看到完整的模式列表,x11vnc的画面恢复正常。如果你的机器有闲置的HDMI或DP接口,这是性价比最高、最稳定的方案。
需要注意两点:选购时确认虚拟头支持你要的分辨率,有些只写到1080p,4K场景不适用;另外部分主机在关机状态下也会给HDMI接口供电,虚拟头长期插着略微发热,但一般不影响使用。
4.2 软件方案:给Xorg补一个假屏幕
如果机器没有物理显卡接口可用(比如某些准系统/虚拟机/云主机),那就得用软件方案,给Xorg配置一个虚拟显示器。
麒麟2403的Xorg配置目录在/etc/X11/xorg.conf.d/,我创建了一个10-headless.conf,内容如下:
Section "Device" Identifier "DummyDevice" Driver "dummy" VideoRam 32768 EndSection Section "Monitor" Identifier "DummyMonitor" HorizSync 30.0-70.0 VertRefresh 50.0-75.0 Modeline "1920x1080" 148.50 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync EndSection Section "Screen" Identifier "DummyScreen" Device "DummyDevice" Monitor "DummyMonitor" DefaultDepth 24 SubSection "Display" Depth 24 Modes "1920x1080" EndSubSection EndSection这个配置里最关键的两处,一个是Driver "dummy",它让Xorg使用一个只存在于内存里的虚拟显卡设备;另一个是DefaultDepth 24,强制色深为24位真彩。Modeline那一行定义了一个1080p的显示模式,相当于给虚拟屏写了一份固定的“EDID”。
配置完成后重启X或重启系统,xrandr就能看到1920x1080的模式了。
但这里有个非常常见的坑:麒麟2403的安装镜像不一定自带xserver-xorg-video-dummy这个驱动包。如果没有,Xorg会在日志里报No devices detected或者直接回退到默认显卡驱动。需要先确认:
dpkg -l | grep xserver-xorg-video-dummy如果没装,用软件源安装:
sudo apt install xserver-xorg-video-dummy我自己的系统里软件源是能搜到该包的,如果你的软件源没有,那就老实买一个HDMI虚拟插头,别在软件方案上死磕。
4.3 两套方案怎么选
| 对比项 | HDMI虚拟插头 | Xorg dummy驱动 |
|---|---|---|
| 成本 | 十几二十元 | 免费 |
| 稳定性 | 非常高 | 取决于配置质量 |
| 适用场景 | 有HDMI/DP物理接口 | 虚拟机、云主机、物理接口不可用 |
| 对硬件的要求 | 需要占用一个视频输出口 | 无特殊要求 |
| 3D加速/硬解 | 保留真实显卡能力 | 无硬件加速,软件渲染 |
| 部署复杂度 | 插上即用 | 需要写配置、装驱动包 |
一个容易被忽略的点:如果你的无头机器还要跑3D渲染、视频硬解或游戏,dummy驱动方案会让你彻底失去GPU硬件加速,因为虚拟显卡没有任何3D能力。这种情况必须用硬件虚拟插头,让真实显卡保持完整能力。
5. x11vnc参数与服务化:远程体验的最后一块拼图
5.1 几组关键参数的实际含义
画面恢复正常之后,x11vnc的参数也值得重新调一遍。无头远程桌面场景下,我推荐这样一组参数:
x11vnc -forever -shared -repeat -noipv6 -rfbport 5900 \ -display :0 -auth guess \ -passwd 你的密码 \ -ncache 10简单解释一下几个容易被忽视的参数:
-forever:客户端断开后服务不退出,否则VNC连接一关进程就没了-repeat:允许按键自动重复,对远程操作很有必要-auth guess:自动猜测Xauthority认证文件路径,解决权限导致的黑屏问题-ncache 10:开启客户端本地缓存,可显著减少远程画面滚动的卡顿感-noipv6:避免部分IPv6网络环境下连接时报错
参数不要盲目照抄,如果你只有一个用户且不担心局域网访问安全,可以不加passwd;如果走公网,建议加-ssl或者用SSH隧道,不要只靠VNC密码裸奔。
5.2 注意VNC连上后画面还是灰/黑的情况
画面花屏解决后,有些人会遇到另一个问题:VNC连上了,但屏幕整个是灰的或黑的,只有鼠标能动。这通常是x11vnc权限不够,无法读到当前用户的X会话内容。解决方法是确认-display :0对应你的图形会话编号,并使用-auth guess。
还有一个容易踩的坑:如果麒麟2403默认显示管理器唤醒的不是Xorg,而是Wayland,x11vnc是没法直接抓屏的。2024年之后的麒麟版本在部分机器上会默认尝试Wayland。可以用echo $XDG_SESSION_TYPE确认,如果显示wayland,要么在登录管理器里改成Xorg会话,要么改用Wayland原生远程方案。x11vnc只对付X11。
5.3 用systemd托管x11vnc,别再nohup裸跑
以前我图省事,用nohup x11vnc ... &直接后台跑,问题很多:机器重启后要手动拉起来,进程还可能被系统异常杀掉。规范做法是写一个systemd服务。
创建/etc/systemd/system/x11vnc.service:
[Unit] Description=x11vnc remote desktop service After=display-manager.service network.target [Service] Type=simple ExecStart=/usr/bin/x11vnc -forever -shared -repeat -noipv6 -rfbport 5900 -display :0 -auth guess -passwd 你的密码 -ncache 10 Restart=on-failure RestartSec=3 [Install] WantedBy=multi-user.target注意After=display-manager.service这行很重要。它确保图形会话已经起来之后才启动x11vnc,否则服务可能在Xorg还没完成初始化时就启动,导致抓屏失败。配置完成后:
sudo systemctl daemon-reload sudo systemctl enable --now x11vnc实测下来,这样托管之后即使机器意外掉电重启,x11vnc也会自动跟着桌面起来,远程连接再也不用人工干预。
6. 同根问题延伸:微信显示异常与虚幻引擎游戏花屏闪退
6.1 图形栈是全局的:分辨率、缩放和渲染
x11vnc花屏的根因是图形栈底层参数异常,这个结论其实可以延伸到很多麒麟2403的“舆论热点”上。比如当时网上讨论度很高的“银河麒麟2403微信下载后显示异常”、“玩普通游戏没问题,玩虚幻引擎游戏就花屏闪退”,本质上都和图形栈的健康程度有关。
分辨率识别错误、色深异常、GPU驱动没有正确加载,影响的绝不只是VNC远程画面。Qt程序、Electron应用、3D游戏渲染,全部跑在同一套图形栈之上。底层参数歪了,上层应用表现各异:轻的显示模糊、字体发虚、窗口边框错乱,重的直接花屏闪退。
6.2 微信在麒麟2403上的常见显示问题
微信Linux版在麒麟2403上的问题,常见的是安装后界面模糊、字体发虚、部分区域闪烁。很多人以为这是微信本身适配差,其实有一个变量是系统分辨率/缩放在无头或异常EDID环境下被搞乱了。
修复思路分两步。第一步,确认系统分辨率是否符合屏幕物理分辨率,用xrandr调整到原生分辨率;第二步,调整显示缩放。麒麟的UKUI设置中心里可以设置缩放比例,有些版本的微信是Qt程序,会受QT_SCALE_FACTOR或QT_QPA_PLATFORM=wayland/xcb影响。
如果字符发虚,可以试着在启动微信前加上:
export QT_QPA_PLATFORM=xcb export QT_SCALE_FACTOR=1 ./wechat这个组合在我自己的机器上解决过几次字体虚、窗口错位的问题。需要注意,这是Qt类程序的通用排查手段,不限于微信。
6.3 普通游戏正常、虚幻引擎游戏花屏闪退怎么查
“普通游戏没问题,玩虚幻引擎游戏就花屏闪退”这个现象,和VNC花屏有点类似,属于“同一症状、不同层级”。
普通小游戏对渲染要求低,很多是CPU软渲染也能扛,所以OpenGL/Vulkan状态不对它们也能凑合跑。虚幻引擎类游戏对图形API版本、GPU驱动完整性要求极高,底层稍有问题,加载着色器阶段就会出现花屏、材质错乱、闪退。
排查方向主要有三个。
第一个,确认系统到底用没用到GPU硬件加速。终端执行:
glxinfo | grep -E "renderer|vendor"如果输出里出现llvmpipe,说明OpenGL正在用CPU软件渲染,而不是GPU。这种状态下len跑虚幻引擎游戏必花屏闪退。llvmpipe是用一套软件算法模拟GPU渲染,基础兼容性有了,但性能和某些复杂特性完全不够。
第二个,检查Vulkan支持:
vulkaninfo --summary如果报错或找不到设备,说明系统没有安装Vulkan驱动,需要装mesa-vulkan-drivers和对应的厂商驱动。发行版自带的软件源里一般都有:sudo apt install mesa-vulkan-drivers。
第三个,确认显卡驱动确实是硬件厂商闭源驱动或完好的开源驱动,而不是 fallback 到了modesetting之类。对NVIDIA卡,检查nvidia-smi是否正常;对AMD和Intel核显,检查/dev/dri下是否有renderD128设备节点。
这个排查链和解决无头花屏的逻辑是一致的:先确认显示服务、分辨率、色深、GPU驱动这些底层“基础设施”是否健康,再看具体应用的兼容问题。底层没打好底,上层各种毛病都很正常。
7. 复盘与经验沉淀:无头环境的检查清单与建议
7.1 别把时间浪费在重装桌面上
这次折腾最大的教训是:碰到图形相关异常,不要先想重装,先想取证。重装桌面耗时半小时起步,重装系统更久,但大部分图形问题在启动日志里已经写了答案。Xorg.0.log、dmesg、xrandr这几个工具的优先级远高于安装命令。
我把这次无头花屏的经验总结成一个判断链:
- 花屏是否本地和远程同时存在?是,则问题在X层;否,则检查VNC传输。
dmesg | grep -i edid有没有报EDID获取失败?有,则问题在于缺少显示器信息。xrandr可用分辨率列表是不是只有640x480/800x600?是,则显卡没有读到有效模式。- Xorg日志里的Depth是不是16或更低?是,则颜色映射错乱导致视觉花屏。
走完这四步,问题就已经从“玄学”变成了“配置项”。
7.2 一套可复用的无头麒麟环境检查命令
把这次用到的排查命令整理成一张速查表,方便下次遇到类似问题直接抄作业:
| 检查目的 | 命令 | 预期正常结果 |
|---|---|---|
| 查看EDID获取情况 | sudo dmesg | grep -i edid | 有显示器名/分辨率信息 |
| 查看当前分辨率和色深 | xrandr | 1920x1080,24位模式可选 |
| 查看Xorg启动参数 | sudo grep -Ei "screen|depth|fbbpp" /var/log/Xorg.0.log | Depth 24,fbbpp 32 |
| 查看显卡实际渲染驱动 | glxinfo | grep -E "renderer|vendor" | 出现真实GPU型号,不是llvmpipe |
| 查看Vulkan设备 | vulkaninfo --summary | 枚举出硬件设备 |
| 查看x11vnc服务状态 | systemctl status x11vnc | active (running) |
这六条命令基本覆盖了绝大多数麒麟无头图形问题的诊断场景,不用装额外的诊断工具,全是系统自带。
7.3 如果重新来一次,我会先把这四件事做对
第一,机器固定位置之前,直接插一个HDMI虚拟插头。花十几块钱,杜绝以后所有EDID相关的奇葩问题。
第二,从一开始就用systemd托管x11vnc,而不是临时后台启动。服务化之后重启自动恢复,省掉大量重复操作。
第三,遇到图形问题先看日志再动手。我这次重装桌面浪费的时间,足够我把日志从头到尾读三遍。
第四,严格区分“底层图形栈”和“应用层”问题。底层问题用xrandr、日志判断;应用层问题才考虑重装软件和桌面。
最后说一点个人体会。麒麟2403本身作为国产桌面系统的日常稳定性是够用的,但这类系统在无显示器、远程桌面等“非典型使用场景”下的调优资料确实少,官方文档也偏少,遇到问题只能靠日志和自己折腾。这次x11vnc花屏折磨了我两天,但搞明白EDID和色深的逻辑之后,我反而觉得这类问题并不神秘——显卡驱动、显示服务器、远程抓屏这三层之间的关系是确定的,每一层的错误都有日志可查。只要按“先看底层、再查应用、别乱重装”的顺序走,多数花屏问题都能定位到具体的配置项,而不是靠碰运气。希望这篇记录能帮你省下那两天。