vnc xfce

最后发布时间 : 2026-09-23 12:08:16 浏览量 :

Read memory

Created memory file

结论

黑屏跟 --user $(id -u):$(id -g) 无关,是宿主机 Docker 默认 seccomp 拦截了 close_range 系统调用,导致容器里 Xfce 桌面组件全部启动失败。

排查证据

1. VNC 本身是好的 —— Xvnc 和 noVNC 都正常起来了:

Xtigervnc :1 -rfbport 5901 -geometry 1920x1080 -depth 24   # 在跑
python3 -m websockify ... 6901 localhost:5901              # 在跑

所以你连上 6901 后能看到画面(而不是连不上)——只是画面里只有一块空白的根窗口 = 黑屏。

2. 桌面是空的 —— ps 里只有 xfce4-session,关键组件一个都没有:

46 xfce4-session     # 在
                      # ❌ 没有 xfwm4 / xfce4-panel / xfdesktop / xfsettingsd

3. wm_startup.log 里找到了根因:

(xfce4-session:158): Unable to launch "xfsettingsd" ...:
    Failed to close file descriptor for child process (Operation not permitted)
(xfce4-session:158): Unable to launch "light-locker" ...: 同上
(xfce4-session:158): Unable to launch "xiccd" ...: 同上
(xfce4-session:158): Unable to launch xfce4-notifyd ...: 同上
(xfce4-session:158): Unable to launch polkit-gnome-...: 同上

xfce4-session 启动任何子进程都失败了 → 没有窗口管理器、没有面板、没有桌面图标 → 黑屏。

为什么会这样

GLib 的 g_spawn 会调用 Linux 5.9+ 才有的 close_range(2) 来关闭子进程的文件描述符。实测你这台机器:

场景close_range 返回
Docker 默认 seccompEPERM(被 seccomp 拦截)
--security-opt seccomp=unconfinedENOSYS(内核 5.4 本来就没这syscall)

原因链:你的 Docker 是 20.10.18,内核 5.4.0-26,而 Ubuntu 20.04 的 libseccomp < 2.5.0 不认识 close_range 这个名字 → Docker 默认 profile 里那条 allow 规则被静默丢弃 → 未匹配的 syscall 按 SCMP_ACT_ERRNO(EPERM) 处理 → 返回 EPERM。而 GLib 只在 ENOSYS 时优雅回退,遇到 EPERM 直接硬失败,于是每个 g_spawn 都挂。

顺带验证:不加 --user(用镜像默认 uid 1000)同样是 EPERM,所以 --user 不是元凶——这个镜像本来就靠 nss_wrapper(generate_container_user + LD_PRELOAD)支持任意 UID。

修复(已实测有效)

加上 --security-opt seccomp=unconfined:

docker run --rm --user $(id -u):$(id -g) \
  --security-opt seccomp=unconfined \
  -p 6901:6901 \
  -e VNC_RESOLUTION=1920x1080 \
  -e VNC_PASSWORDLESS=true \
  registry.cn-hangzhou.aliyuncs.com/wybioinfo/debian-xfce-vnc

验证结果 —— 桌面组件全部正常:

139 xfwm4
161 xfsettingsd
164 xfce4-panel
173 xfdesktop

备选方案:宿主机把 libseccomp2 升到 ≥ 2.5.0(focal-updates 有)并重启 docker,这样那条 allow 规则生效,close_range 在 5.4 内核上返回 ENOSYS,GLib 就能正常回退——比 unconfined 更安全;或者自备一份允许 close_range 的 seccomp profile。

补充

修复后日志里剩下的这些是无害噪音,不用管(容器内没有 systemd / system D-Bus / pulseaudio):

  • could not get proxy for org.freedesktop.login1
  • light-locker: session_id is not set
  • polkit-gnome: Could not connect
  • pa_context_connect() failed

我已把这条环境陷阱记进仓库记忆 docker-runtime-notes.md,后续遇到容器内 GTK/Python GUI 程序莫名起不来可以直接查。