GNOME 录屏卡死排查与修复(Ubuntu 22.04 + GNOME 42)

环境信息

项目版本
系统Ubuntu 22.04 LTS
桌面GNOME Shell 42.9
会话类型Wayland
音视频框架PipeWire 0.3.x
Portalxdg-desktop-portal-gnome 42.1
机器Dell OptiPlex 7080

问题现象

操作步骤

  1. 按下 Ctrl+Shift+Alt+R 触发 GNOME 内置录屏功能
  2. 屏幕出现录屏 UI 界面,可以正常选择录制区域(全屏/窗口/自定义区域)
  3. 点击”录制”按钮或选择区域确认后

预期行为

屏幕顶部出现红色录制指示器,开始录屏。

实际行为

  • 选择区域后没有任何反馈,录屏未开始
  • 屏幕顶部没有出现红色录制指示器
  • 没有弹出任何错误提示
  • 重复尝试多次均失败,表现完全一致
  • 首次尝试会卡顿约 25 秒后静默失败,后续尝试几乎立即失败

影响范围

  • GNOME 内置录屏功能完全不可用
  • 截图功能(Print 键)不受影响
  • 第三方录屏工具(OBS 等)不受影响

排查过程

1. 确认快捷键绑定

gsettings list-recursively org.gnome.shell.keybindings | grep -i "screen\|record"

输出确认快捷键已正确绑定:

org.gnome.shell.keybindings show-screen-recording-ui ['<Ctrl><Shift><Alt>R']
org.gnome.shell.keybindings show-screenshot-ui ['Print']

结论:快捷键正常,排除绑定问题。

2. 检查 GStreamer 依赖

GNOME 录屏依赖 GStreamer 的 VP8 编码器、WebM 封装器和 PipeWire 源:

gst-inspect-1.0 vp8enc    # VP8 编码器
gst-inspect-1.0 webmmux   # WebM 封装器
gst-inspect-1.0 pipewiresrc  # PipeWire 屏幕捕获源

三个插件均正常存在。结论:排除依赖缺失。

3. 查看系统日志(关键步骤)

journalctl --user --since "30 min ago" | grep -i "screencast\|Error starting"

发现大量错误:

10:32:19 dbus-daemon: Activating service name='org.gnome.Shell.Screencast'
10:32:20 dbus-daemon: Successfully activated service 'org.gnome.Shell.Screencast'
10:32:45 gnome-shell: Error starting screencast: 已到超时限制     ← 首次尝试,25秒后超时
10:32:58 gnome-shell: Error starting screencast                  ← 后续尝试立即失败
10:33:36 gnome-shell: Error starting screencast
10:33:47 gnome-shell: Error starting screencast
10:34:16 gnome-shell: Error starting screencast
...
10:38:25 dbus-daemon: Activating service name='org.gnome.Shell.Screencast'  ← 杀进程后重试
10:38:25 dbus-daemon: Successfully activated service 'org.gnome.Shell.Screencast'
10:38:50 gnome-shell: Error starting screencast: 已到超时限制     ← 仍然超时

规律

  • Screencast D-Bus 服务被激活后,约 25 秒超时失败
  • 首次超时后,后续请求全部立即失败(因为前一个 Screencast 进程卡死占用了资源)
  • 即使杀死卡死进程重启 portal,新启动的 Screencast 进程仍然超时

4. 检查进程状态

ps aux | grep "org.gnome.Shell.Screencast" | grep -v grep

发现一个卡死的 Screencast 进程:

zbc  809541  0.0  0.0 3370644 53696 ?  Sl  10:32  0:00  /usr/bin/gjs /usr/share/gnome-shell/org.gnome.Shell.Screencast

该进程启动后未能正常完成初始化,处于僵死状态,阻塞了所有后续录屏请求。

5. 检查 PipeWire 运行时间(定位根因)

systemctl --user status pipewire.service | grep "Active:"
Active: active (running) since Sat 2026-05-09 11:18:47 CST; 4 days ago

PipeWire 已连续运行超过 4 天。结合以下事实:

  • 仅杀死 Screencast 进程 + 重启 portal → 无法修复,新进程仍超时
  • 重启 PipeWire + portal → 立即修复

确认问题出在 PipeWire 长时间运行后管道状态异常。

根因分析

直接原因

org.gnome.Shell.Screencast 进程启动后,尝试通过 PipeWire 建立屏幕捕获流(screencast stream)。由于 PipeWire 服务长时间运行(本例超过 4 天),其内部的 screencast 管道状态异常,无法在 25 秒超时限制内完成流的建立,导致:

  1. 首次请求:Screencast 进程启动 → 等待 PipeWire 流 → 25 秒超时 → 进程卡死残留
  2. 后续请求:检测到已有 Screencast 进程 → 立即返回失败

根本原因

这是 GNOME 42 + PipeWire 0.3.x 的已知缺陷:

  • PipeWire 0.3.x 的 screencast portal 实现存在资源泄漏
  • 长时间运行后,screencast 相关的内部节点/链接状态损坏
  • GNOME 42 的 Screencast 服务没有针对 PipeWire 超时的重试或自恢复机制
  • 该问题在 PipeWire 0.3.6x+ 和 GNOME 43+ 中有显著改善

触发条件

  • Ubuntu 22.04 + Wayland 会话
  • PipeWire 长时间运行(通常 > 2-3 天)
  • 期间可能有其他 PipeWire 客户端(如浏览器屏幕共享)使用过 screencast 流

本次实际解决过程

本次排查经历了两轮修复才最终解决:

第一轮:杀进程 + 重启 portal(失败)

发现 PID 809541 的 Screencast 卡死进程后,执行:

kill 809541
systemctl --user restart xdg-desktop-portal xdg-desktop-portal-gnome

重试录屏 → 恢复正常。但约 5 分钟后再次卡死,日志再次出现 Error starting screencast: 已到超时限制,新的卡死进程 PID 814397。

结论:仅杀进程 + 重启 portal 治标不治本,PipeWire 内部状态已损坏。

第二轮:重启 PipeWire 栈(成功)

systemctl --user restart pipewire xdg-desktop-portal xdg-desktop-portal-gnome

注:最初尝试同时重启 pipewire-pulsewireplumber,但 Ubuntu 22.04 默认未安装这两个服务(报 Unit not found),跳过后仅重启以上三个服务即可。

重启后录屏功能恢复正常,后续多次使用未再复现。

解决方案

方案一:临时修复(治标)

杀死卡死进程 + 重启 portal:

kill $(pgrep -f "org.gnome.Shell.Screencast")
systemctl --user restart xdg-desktop-portal xdg-desktop-portal-gnome
  • 适用场景:PipeWire 本身状态正常,仅 Screencast 进程卡死
  • 缺点:如果 PipeWire 状态已损坏,此方案无效

方案二:重启 PipeWire 栈(推荐)

systemctl --user restart pipewire xdg-desktop-portal xdg-desktop-portal-gnome
  • 适用场景:PipeWire 长时间运行后 screencast 管道异常
  • 副作用:正在进行的音频播放会短暂中断(约 1 秒),其他应用不受影响
  • Ubuntu 22.04 默认未启用 pipewire-pulsewireplumber,无需重启

方案三:一键修复脚本

将以下脚本保存为 ~/bin/fix-screencast.sh,遇到问题时一键执行:

#!/bin/bash
# 修复 GNOME 录屏卡死问题
echo "正在检查 Screencast 进程..."
PIDS=$(pgrep -f "org.gnome.Shell.Screencast")
if [ -n "$PIDS" ]; then
    echo "发现卡死的 Screencast 进程: $PIDS,正在清理..."
    kill $PIDS 2>/dev/null
    sleep 1
fi
 
echo "正在重启 PipeWire 和 Portal 服务..."
systemctl --user restart pipewire xdg-desktop-portal xdg-desktop-portal-gnome
 
echo "等待服务就绪..."
sleep 2
 
# 验证
if systemctl --user is-active pipewire >/dev/null 2>&1 && \
   systemctl --user is-active xdg-desktop-portal-gnome >/dev/null 2>&1; then
    echo "修复完成,请重试 Ctrl+Shift+Alt+R 录屏"
else
    echo "服务重启异常,请检查日志:journalctl --user --since '1 min ago'"
fi

方案四:长期根治

升级系统(如条件允许):

  • 升级到 Ubuntu 24.04 LTS(GNOME 46 + PipeWire 1.0.x),该问题已基本解决
  • 或单独升级 PipeWire 到 0.3.65+(通过 PPA),有显著改善

定期重启 PipeWire(如无法升级):

创建 systemd timer 每天自动重启一次 PipeWire:

# ~/.config/systemd/user/pipewire-restart.service
[Unit]
Description=Restart PipeWire to prevent screencast stale state
 
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl --user restart pipewire xdg-desktop-portal xdg-desktop-portal-gnome
 
# ~/.config/systemd/user/pipewire-restart.timer
[Unit]
Description=Daily PipeWire restart
 
[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true
 
[Install]
WantedBy=timers.target

启用:

systemctl --user daemon-reload
systemctl --user enable --now pipewire-restart.timer

快速诊断命令汇总

# 一键诊断
echo "=== 会话类型 ===" && echo $XDG_SESSION_TYPE \
&& echo "=== PipeWire 运行时间 ===" && systemctl --user status pipewire.service | grep Active \
&& echo "=== Portal 状态 ===" && systemctl --user status xdg-desktop-portal-gnome.service | grep Active \
&& echo "=== 卡死进程 ===" && ps aux | grep "org.gnome.Shell.Screencast" | grep -v grep \
&& echo "=== 最近错误 ===" && journalctl --user --since "10 min ago" | grep -i "screencast\|Error starting" | tail -5
 
# 一键修复
systemctl --user restart pipewire xdg-desktop-portal xdg-desktop-portal-gnome