☰
Ubuntu虚拟显示驱动完整指南:dummy与Xvfb解决无头图形环境
2026/10/1 7:01:17 网站建设 项目流程

很多人在 Ubuntu 服务器上折腾过这样一件事:机器明明没有接显示器,却非要跑一个需要图形界面的程序,或者要在 CI 环境里做界面自动化测试。装好系统后打开 VNC 一看,要么分辨率小得可怜,要么直接黑屏。这时候就该轮到虚拟显示驱动上场了。

虚拟显示驱动说白了就是给“没有物理屏幕的机器”装一块虚拟显卡,让系统以为有一台显示器连着。这样 X Server 能正常启动,桌面环境能加载,各种图形应用也有地方渲染。最常用的两个工具是xserver-xorg-video-dummy和Xvfb,这俩我都实际用过,踩过不少坑,今天把 Ubuntu 下安装虚拟显示驱动的完整过程、配置细节和排查经验一次性讲清楚。

1. 虚拟显示驱动到底解决什么问题

1.1 没接屏幕的服务器为什么还需要“显卡”

很多人一开始不理解:服务器本来就不需要屏幕,直接 SSH 进去跑命令行不就行了?问题是很多软件默认就离不开显示环境。比如 Chrome 做自动化截屏、Selenium 跑网页测试、Qt 应用做渲染验证、图像处理工具链需要调用 X11,这些程序启动时都会检测 DISPLAY 变量,找不到显示服务就直接崩溃退出。

物理显卡在这种情况下也没法帮你。服务器通常没有独立显卡,就算有,没接显示器时很多驱动会进入省电模式,或者干脆不再输出画面。再加上机房环境根本不可能给你接一台真实显示器,于是虚拟显示驱动就成了唯一可行的路。

它的原理不复杂:在内核和 X Server 之间模拟一个 frame buffer 设备,X Server 向这块“虚拟显卡”写像素数据,数据保存在内存里而不是真正输出到物理屏幕。后续通过 VNC、x11vnc、ffmpeg 甚至直接截图工具拿到的画面,都来自这块内存区域。

1.2 常见使用场景梳理

根据我实际经手的项目,虚拟显示驱动最有价值的场景大概有这么几类:

  • 无头服务器跑图形化 CI 测试:代码仓库里跑 Playwright、Selenium 之类的端到端测试,浏览器不启动图形环境根本没法工作。虚拟显示驱动给了浏览器一个稳定的“显示器”。
  • 远程桌面与 VNC 服务:用 x11vnc 共享桌面时,没有真实显示器就会黑屏或报错。虚拟显示驱动保证桌面始终有输出。
  • 多分辨率并发测试:移动端、PC 端 UI 自动化测试经常需要不同分辨率,物理显示器要手动调,虚拟驱动直接写配置文件就能快速切换。
  • 视频编码与流媒体推流:无头机器需要在黑场状态下渲染视频或推流,虚拟显示驱动可以提供固定分辨率、固定帧率的渲染空间。
  • 深度学习与渲染农场节点:一些可视化验证脚本需要 OpenGL 上下文,虚拟显示驱动配合 Mesa 的软件渲染可以跑起来。

一句话总结:凡是程序要求“你必须有屏幕”而你手上又没有真屏幕的场景,虚拟显示驱动都是最省事的解法。

2. 方案选型:dummy、Xvfb、Weston headless 到底选哪个

2.1 xserver-xorg-video-dummy:最接近真实环境的 X11 方案

xserver-xorg-video-dummy是 Xorg 官方维护的驱动,安装后会在 X Server 启动时加载一个叫dummy的显卡驱动模块。它最大的特点是系统会以为存在一块物理显卡和一台物理显示器,X11 协议里的显示模式、屏幕尺寸、刷新率都会正常上报。

我之所以在日常工作中优先选它,是因为很多图形程序会检测硬件信息。用 software rendering 时部分程序会主动降级,而 dummy 驱动配合 Mesa 的 llvmpipe 渲染,几乎所有 OpenGL 应用都能正常跑起来。它的稳定性和兼容性比 Xvfb 好得多,尤其在跑 Electron、Chromium 这类重度图形应用时特别明显。

代价就是配置略繁琐。需要手写 xorg.conf,指定驱动类型、显示器参数、分辨率模式,文件写得不对分分钟踩坑。

2.2 Xvfb:轻量但别指望它能跑满 OpenGL

Xvfb(X Virtual Framebuffer)是另一个方案,它直接在内存里模拟帧缓冲,不需要写 xorg.conf,一条命令就能拉起一个虚拟显示:

Xvfb :99 -screen 0 1920x1080x24 & export DISPLAY=:99

这个方案确实简单粗暴,适合快速跑测试脚本。但它有几个先天短板:

  • 不支持 DRI 3 相关的硬件加速接口,虽然能跑 OpenGL,但路径较绕,性能也受限。
  • 某些对显示驱动有强校验的软件会报错,因为它不会报告具体的显卡型号和驱动名。
  • 没有虚拟显示器的 EDID 信息,部分应用读取显示器参数时会返回空值。

所以我的经验是:临时调试用 Xvfb,长期稳定跑服务用 dummy。如果你要配置开机自启、多分辨率切换、或者跑生产环境的自动化任务,dummy 是更靠谱的选择。

2.3 选型对照表

对比项xserver-xorg-video-dummyXvfb
配置复杂度需要手写 xorg.conf一条命令即可启动
虚拟硬件信息完整上报显卡与显示器无硬件信息上报
OpenGL 兼容性较好,配合 Mesa 稳定可用,但部分应用兼容性差
多显示器支持支持配置多个虚拟显示器通过多个 screen 模拟,较麻烦
分辨率切换改配置重载 X Server重启 Xvfb 进程
适合场景长期服务、生产任务、桌面共享临时测试、脚本调用

Weston headless 我也简单试过,它是 Wayland 协议下的无头渲染方案。如果你整个环境已经切到 Wayland,可以考虑,但对大多数 Ubuntu 用户来说 X11 体系下的 dummy 更成熟、社区资料更多,也不容易踩 Wayland 特有的兼容坑。

3. Ubuntu 下完整安装与配置过程

3.1 安装驱动与依赖

如果你用的是 Ubuntu 20.04 以上的版本,Xorg 服务本身基本预装,但 dummy 驱动可能需要手动安装。执行:

sudo apt update sudo apt install xserver-xorg-video-dummy xorg x11-utils mesa-utils

x11-utils主要提供xdpyinfo和xrandr这两个查询工具,验证虚拟显示是否生效离不开它们。mesa-utils里有glxinfo和glxgears,用来验证 OpenGL 渲染是否正常,这个后面会用到。

有些极简系统连 X Server 本体都没有,那还需要额外装xserver-xorg-core。装完后输入Xorg -version能看到版本号就说明 X Server 可以用了。

3.2 手工编写 dummy 驱动 xorg.conf

这是整个流程里最核心的一步。xorg.conf 是 X Server 的主配置文件,dummy 驱动的所有参数都靠它控制。我的习惯是先建一个独立配置文件:

sudo mkdir -p /etc/X11/xorg.conf.d sudo vim /etc/X11/xorg.conf.d/10-dummy.conf

内容如下,这份配置我在多台机器上验证过,直接复用它基本能支撑 1920x1080 的虚拟桌面:

Section "Device" Identifier "DummyDevice" Driver "dummy" VideoRam 256000 EndSection Section "Monitor" Identifier "DummyMonitor" HorizSync 10.0 - 100.0 VertRefresh 10.0 - 200.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

几个参数值得解释一下。

VideoRam是给虚拟显卡分配的显存,单位是 KB。这里设 256000,即约 250 MB。1920x1080x24bit 的画面一帧约为 1920 * 1080 * 3 = 6220800 字节,约 6.2 MB,就算开双缓冲也绰绰有余。如果你的分辨率更高,比如 4K,建议直接按 512000 设置。

HorizSync和VertRefresh是显示器行频和场频范围,dummy 驱动没有真实显示器可以探测,所以必须手动给一个范围。10.0 到 200.0 已经能覆盖绝大多数 Modeline 的需求,设小了你后续想加新分辨率时会遇到“Mode out of range”的报错。

Modeline是重点。这一行定义了显示模式的具体时序参数,包括像素时钟、前肩、后肩、同步脉冲宽度。很多人不理解为什么要手动算这个,其实 dummy 驱动不读 EDID,就没有显示器主动上报时序,X Server 也不知道该输出什么格式,只能靠 Modeline 告诉它。上面这一条实际是对应标准 HDMI 1080p 的 CEA-861 时序:像素时钟 148.5 MHz,水平有效像素 1920,同步参数依次是 2008、2052、2200,垂直方向是 1080、1084、1089、1125。这是行业内约定俗成的标准值,直接抄没问题。

3.3 自定义分辨率的计算方法

这里得岔开讲一下 Modeline 的计算逻辑,否则你换个非标分辨率就只能瞎试了。

Modeline 格式是:

Modeline "名称" 像素时钟 水平有效 水平前肩 水平同步 水平总计 垂直有效 垂直前肩 垂直同步 垂直总计 [标志]

像素时钟的公式约等于:

像素时钟 = 水平总像素 × 垂直总行数 × 刷新率

以 1920x1080@60 为例,水平总计是 2200,垂直总计是 1125,60 Hz 帧率,那么像素时钟就是 2200 * 1125 * 60 = 148.5 MHz,跟上面标准值完全一致。

如果你想做 2560x1440@60,用手算比较费劲,建议直接用cvt命令自动生成:

cvt 2560 1440 60

输出里会有一整行 Modeline,把它复制进配置文件替换原来的 Modeline 即可。如果是 4K,可以先跑cvt 3840 2160 60,但如果刷新率超过 60 得注意像素时钟不能过大,否则虚拟显卡可能吃不下。

在Screen部分的 SubSection 里填Modes "2560x1440",名称必须和 Modeline 的名称一致。系统会默认匹配第一个可用的模式,以后想切分辨率就靠xrandr --size 2560x1440。

配置完成后重启 X Server 或者重启机器,然后检查是否生效:

xdpyinfo | grep dimensions

如果输出为dimensions: 1920x1080 pixels就说明虚拟显示驱动加载成功了。

4. 让虚拟显示开机自启并稳定运行

4.1 systemd 服务该怎么写

只启动一次还不够,生产环境需要开机自动拉起,不然服务器一重启你的自动化任务就全部瘫在那里。我在多数 Ubuntu 服务器上采用如下 systemd 单元配置:

sudo vim /etc/systemd/system/xvfb-dummy.service
[Unit] Description=Xorg with dummy driver After=systemd-user-sessions.service After=network.target [Service] Type=simple Environment=DISPLAY=:1 ExecStart=/usr/bin/Xorg :1 -config /etc/X11/xorg.conf.d/10-dummy.conf -keeptty -noreset -nolisten tcp vt7 Restart=always RestartSec=5 User=root [Install] WantedBy=multi-user.target

启动参数里几个值得注意的点:

-keeptty让 Xorg 占用当前虚拟终端而不是主动切走,vt7指定使用 tty7,这是传统图形界面所在的终端。-nolisten tcp禁掉 TCP 监听,避免无意义的网络暴露。

Restart=always配合RestartSec=5能应对 X Server 偶发崩溃,这个选项帮我避免过不少次凌晨跑挂的尴尬。

然后执行:

sudo systemctl daemon-reload sudo systemctl enable xvfb-dummy.service sudo systemctl start xvfb-dummy.service

注意一个细节:如果你把DISPLAY=:1写进了服务文件,后续其他程序要想连接这个显示,也得在环境变量里带上DISPLAY=:1。很多人配置完服务发现程序还是连不上,大概率就是 DISPLAY 没对上。

4.2 VNC 远程桌面里的注意事项

dummy 驱动本身不提供远程画面传输能力,它只负责“渲染画面到内存”。要真正看到画面,得搭配x11vnc或Xvnc。我这里最常用的是 x11vnc:

sudo apt install x11vnc x11vnc -display :1 -forever -shared -rfbport 5900 -rfbauth ~/.vnc/passwd

-forever让连接断开后服务不退出,-shared允许多个客户端同时连接。密码文件要先通过x11vnc -storepasswd生成一次。

这里有个经验:x11vnc 的输出帧缓冲依赖 Xorg 的画面,dummy 驱动本身没有硬件加速,远程桌面在高分辨率下画面刷新会偏慢,如果只用于鼠标键盘操作没多大问题,但看视频或者拖动画布会有卡顿。所以我建议虚拟显示分辨率不要盲目拉满,够用就行。

4.3 DISPLAY 变量和常见环境坑

在 bash 环境里,每次启动图形程序前要确保 DISPLAY 指向正确的显示编号。可以在全局配置里直接写:

echo 'export DISPLAY=:1' >> ~/.bashrc source ~/.bashrc

如果程序是通过 supervisor 或 cron 启动的,注意这些工具默认不会加载用户的.bashrc,所以一定要在启动命令前显式加上环境变量,写成类似这种形式:

DISPLAY=:1 python3 /opt/test.py

另一个常见坑是 Wayland 和 X11 的冲突。Ubuntu 22.04 默认 GNOME 桌面用的登录会话可能是 Wayland,但 Xorg 的 DISPLAY 变量仍然指向 X11 端口。如果你在一个没有真实桌面的服务器上只跑了 Xorg,那所有 Wayland 程序根本不会认DISPLAY。解决方法是优先保证虚拟显示是 X11 会话,Wayland 程序如果要强行跑,要么加--ozone-platform=x11之类参数,要么就用专门为 Wayland 准备的 headless 方案。这个不是今天的主角,先不展开。

5. 常见问题排查手册

5.1 分辨率不生效,始终只有 1024x768

这是最典型的坑。dummy 驱动刚启动时如果没有读取到正确的 Modeline,X Server 会退回内部默认模式,通常是 1024x768。

优先检查 xorg.conf 里的Modes "1920x1080"是否和 Modeline 名称严格一致,大小写、空格都可能造成不匹配。

接着用xdpyinfo查看所有可用显示模式:

xdpyinfo -display :1 | grep -A 100 "screen #0"

如果模式列表里没有 1920x1080,说明 Modeline 没被正确加载。改用cvt重新生成 Modeline 并替换再试一次。

还有一种隐蔽情况:Xorg 启动时用了多个配置文件,且后面加载的配置覆盖了你的 dummy 配置。可以用Xorg -configure生成当前配置的完整 dump 看看实际生效参数。

5.2 启动时报错 failed to load module dummy

这种通常就是驱动包没装好,或者软件源里没有对应版本。先确认:

ls /usr/lib/xorg/modules/drivers/dummy_drv.so

如果文件不存在,回到第 3.1 步重新安装xserver-xorg-video-dummy。Ubuntu 某些精简定制版本可能把 xorg-modules 整体阉割掉,直接执行:

sudo apt install xserver-xorg-video-dummy xserver-xorg-core

装完重建模块索引,重新启动 Xorg。个别情况下还需要卸载后重装一次,清理残留的模块加载状态。

5.3 程序能启动但 OpenGL 渲染报错

报错信息通常是libGL error: failed to load driver: swrast或Mesa: warning: Failed to open swrast。

dummy 驱动本身不带渲染能力,OpenGL 靠 Mesa 的软件实现层 llvmpipe 完成。这个链路如果断掉,通常是系统里 Mesa 库版本不完整。安装修复:

sudo apt install libgl1-mesa-dri libglx-mesa0 mesa-utils

装好后用glxinfo验证:

glxinfo -display :1 | grep "OpenGL renderer"

能看到llvmpipe字样就说明软件渲染链路正常。如果验证通过但特定应用还报错,优先怀疑应用自己编译时禁用了软件渲染路径。

5.4 问题速查表

现象优先排查点常用解决手段
分辨率固定 1024x768Modeline 是否加载用 cvt 重新生成,检查 Modes 名称
启动失败 failed to load dummy驱动包缺失重装 xserver-xorg-video-dummy
OpenGL 渲染报错Mesa 软件渲染链路安装 libgl1-mesa-dri
程序连接不上 DISPLAY环境变量未生效显式指定 DISPLAY=:1
VNC 显示灰屏x11vnc 和 Xorg 端口不匹配确认 x11vnc 的 -display 指向 :1
systemd 启动后 X 崩溃配置文件语法不合法Xorg -config离线测试配置
重启后服务没起来systemd 未 enablesudo systemctl enable 服务名

排查的时候建议养成一个习惯:先看日志。Xorg 的日志默认在/var/log/Xorg.0.log,如果换了显示编号就是Xorg.1.log。这里面的信息远比“黑屏”“灰屏”这类表象直观,每次改完配置启动后都去扫一眼有没有大写的(EE)行,基本能定位八成问题。

6. 我能分享的实用经验

用了快三年的虚拟显示驱动,最大的体会是“先想清楚用途再选方案”。临时跑个测试脚本,Xvfb 一条命令搞定,谁也不会闲到配置 xorg.conf。但只要这个虚拟屏幕需要稳定存在、需要长时间供多个程序连接、需要自动恢复,dummy 驱动就是绕不开的正确选择。

还有一点容易被忽略:虚拟显示驱动只解决“有没有屏幕”的问题,它不解决“图形性能”的问题。CPU 软件渲染再优化也有上限,如果你真需要 GPU 加速,还是得走物理显卡透传那套路子,虚拟显示驱动不适合硬扛 3D 大场景。

最后再分享一个我自己常用的技巧:准备两份配置模板,一份是 1920x1080,一份是 3840x2160,需要切换分辨率时直接替换配置文件再重启服务,几分钟就能完成整套切换,比在真实显示器上还快。适合做多分辨率 UI 回归测试的同学。把这套配置纳入你的自动化基础设施,省下来的不只是时间,更是半夜被测试失败提示吵醒的命。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询