简介:针对Ubuntu 22.04及以上版本gdm配置方式变更后登录背景修改失效的问题,这份资源提供了一套专用脚本工具,面向希望自定义登录界面的Linux用户与系统管理员。包体共10个文件,以shell脚本为主(含普通背景与透明背景两个变体),附带Markdown说明文档、许可证文件及版本辅助信息,整体约20KB,轻量且便于审阅。脚本按系统版本差异拆分为升级前后两个主要入口,兼顾22.04与后续更新环境,并提供透明化登录界面的附加脚本;README中明确了备份、权限和重启服务等关键注意事项,帮助用户避免因配置失误导致无法登录。除核心背景设置功能外,资源还覆盖从命令查看到文件替换的完整修改思路,适合熟悉基本命令行操作、想在Ubuntu 22.04及更高版本中快速实现登录界面定制的使用者。目前已有1132人学习下载,是一份实用且小巧的登录界面定制工具包。
1. 登录背景改不动?先明白 Ubuntu 22.04 的壁纸被谁锁死了
在 Ubuntu 22.04 上换掉桌面壁纸只需要右键一张图,但重启之后你大概率会发现:登录界面还是那张看腻了的默认图。原因不复杂——登录背景根本不是壁纸,它是 GDM 加载的 GNOME Shell 主题里一段 CSS 画出来的,普通桌面设置碰不到它。这篇笔记要交付的是一个可以直接跑的 bash 脚本:它把系统自带的 gnome-shell-theme.gresource 拆开、塞进你的图片、再重新编译,顺带做好了备份和一键还原。适合用过命令行、不想每次升级都被打回原形的人。
2. GDM 主题机制:为什么改 gsettings 经常没用,重编 gresource 才是正路
先说结论:Ubuntu 22.04 的登录/锁屏背景,最终决定权在 gnome-shell 主题的 CSS 里,不在 gsettings 里。这句话我踩了三次坑才真正信。理解了这一点,后面那套脚本才有意义,否则你只是在一堆无效命令里碰运气。
2.1 登录界面由 gnome-shell 绘制:背景藏在 #lockDialogGroup 这条 CSS 里
GDM 是登录管理器,它拉起的是一个独立的 gnome-shell 进程,和你在桌面里跑的 gnome-shell 分属不同会话。两者共享同一份编译后的主题资源。你在系统设置里换的壁纸是给用户会话用的,GDM 会话根本不读那份配置,所以登录界面纹丝不动。
负责登录和锁屏背景的 CSS 选择器叫#lockDialogGroup。由于主题被打包进二进制 gresource 文件,直接在主题目录里 grep 是什么都找不到的:
$ grep -rn "lockDialogGroup" /usr/share/gnome-shell/theme/大概率没有任何输出。想看到真身,得先把 CSS 从 gresource 里解出来:
gresource extract /usr/share/gnome-shell/gnome-shell-theme.gresource \ /org/gnome/shell/theme/gnome-shell.css | grep -n -A4 'lockDialogGroup'输出里那段规则在 22.04 的 Yaru 主题里大致长这样(节选关键行):
#lockDialogGroup { background-color: #2c001e; background-image: url("resource:///org/gnome/shell/theme/login-background.png"); background-repeat: no-repeat; background-size: cover; }不同更新阶段,这段规则可能只有 background-color 没有 url,或者图片文件名不同,但选择器没变过。我们要做的就是把这段的背景换成自己的图。
提示:锁屏和登录共用同一个
#lockDialogGroup,改一次两边都生效,不需要单独处理。
2.2 三条路对比:gsettings / 替换 css / 重编 gresource
网上最常见的尝试是给 gdm 用户设置壁纸:
sudo -u gdm dbus-run-session -- gsettings set \ org.gnome.desktop.background picture-uri 'file:///tmp/1.jpg'这条命令在某些 GNOME 版本有效,因为那些版本里 GDM 壁纸由 gnome-settings-daemon 绘制;但在 22.04 的 Yaru 主题下,只要#lockDialogGroup写了 background,绘制结果就会把它盖住。结果是时灵时不灵,升级一个小版本还可能从灵变不灵。
第二条路是把gnome-shell.css直接丢到/usr/share/gnome-shell/theme/下覆盖——这条路无效。GDM 启动时按名字加载编译后的 gresource,目录里躺着的散装 CSS 根本不会被读。这个黑匣子特性让不少人误以为自己改错了语法,反复试了好几天。
第三条路才是正路:重编 gresource。解包全部资源 → 改 CSS → 加新图 → 用 glib-compile-resources 重新打包 → 重启 GDM。它能稳定跨小版本生效,不受用户会话设置影响。
| 方案 | 生效链路 | 升级后存活 | 推荐度 |
|---|---|---|---|
| gdm 用户 gsettings | 设置后台读取,但 CSS 会盖住它 | 可能失效 | 不推荐 |
| 覆盖散装 CSS | 根本不被加载 | 无意义 | 不推荐 |
| 重编 gresource | 直接替换主题资源包 | 会被包更新覆盖,需重跑脚本 | 推荐 |
所以下面所有脚本代码都围绕第三条路展开。
2.3 拆开 gresource 看看里面到底有什么
想验证机制,先看资源包里都有什么:
$ gresource list /usr/share/gnome-shell/gnome-shell-theme.gresource /org/gnome/shell/theme/gnome-shell.css /org/gnome/shell/theme/checkbox-off.svg /org/gnome/shell/theme/checkbox-on.svg /org/gnome/shell/theme/close.svg /org/gnome/shell/theme/calendar-today.svg ... (共几十个文件)那条长长的/org/gnome/shell/theme/是资源命名空间前缀,extract 时要用完整路径。每个文件都能单独解出:
mkdir -p /tmp/gdm-theme gresource extract /usr/share/gnome-shell/gnome-shell-theme.gresource \ /org/gnome/shell/theme/gnome-shell.css > /tmp/gdm-theme/gnome-shell.css最关键的一点是:编译是白名单模式——XML 里列了谁,新 gresource 里才有谁。少列一个文件,对应资源就悄悄消失。这就是后面避坑章里「登录界面图标变空白」的直接原因。另外,重编只需要 glib 工具链,不需要装任何开发版组件,门槛比想象中低。
3. 修改登录背景脚本:完整源码与每一步的替换逻辑
这一章直接给可抄作业的脚本。先说清楚前提,再贴完整代码,最后解释每个参数为什么是这个值、改坏时看哪里。
3.1 动手前的依赖检查和图形会话提醒
先确认登录器是 GDM,脚本只对它有效:
systemctl status gdm3 --no-pager | head -n 5如果显示的是 lightdm 或 sddm,这份脚本不适用;Ubuntu 22.04 默认桌面就是 GDM,一般不用改。接着检查工具链:
command -v gresource && command -v glib-compile-resources缺了就装:
sudo apt install libglib2.0-binconvert(ImageMagick)是可选项,脚本缺它时会直接复制原图,但大图会让 GDM 变慢,所以建议一并装上:
sudo apt install imagemagick确认 gresource 文件存在:
ls -l /usr/share/gnome-shell/gnome-shell-theme.gresource提示:切换 tty 用 Ctrl+Alt+F3,跑完后再按 Ctrl+Alt+F1 回图形登录。不要在图形会话里直接跑脚本,下一章第一个坑就是它。
3.2 完整脚本:提取、替换、重编译、重启四步合一
#!/bin/bash # ubuntu-login-bg.sh # 作用: 修改 Ubuntu 22.04+ 的 GDM 登录/锁屏背景 # 用法: # sudo bash ubuntu-login-bg.sh /绝对路径/背景图.jpg # sudo bash ubuntu-login-bg.sh --restore set -euo pipefail PREFIX="/org/gnome/shell/theme" GRESOURCE="" find_gresource() { # 22.04 固定在 /usr/share/gnome-shell/ 下, 新版可能挪到 theme 子目录 if [ -f "/usr/share/gnome-shell/gnome-shell-theme.gresource" ]; then GRESOURCE="/usr/share/gnome-shell/gnome-shell-theme.gresource" else GRESOURCE=$(find /usr/share/gnome-shell -maxdepth 3 \ -name 'gnome-shell-theme.gresource' 2>/dev/null | head -n1) fi } usage() { echo "用法: sudo $0 <背景图片> | sudo $0 --restore" exit 1 } [ $# -lt 1 ] && usage find_gresource [ -n "$GRESOURCE" ] || { echo "找不到 gnome-shell-theme.gresource, 确认用的是 GDM"; exit 1; } BACKUP="${GRESOURCE}.orig" # 图形会话内重启 GDM 会直接结束当前桌面, 先拦住 if [ -n "${DISPLAY:-}" ]; then echo "警告: 当前在图形会话内, GDM 重启后桌面进程会被一起结束。" read -r -p "建议先切到 tty (Ctrl+Alt+F3) 再跑, 仍要继续? [y/N] " ans [[ "${ans,,}" == "y" ]] || exit 0 fi restore() { [ -f "$BACKUP" ] || { echo "没有可用备份: $BACKUP"; exit 1; } sudo cp "$BACKUP" "$GRESOURCE" echo "已从备份恢复, 即将重启 GDM ..." sudo systemctl restart gdm3 exit 0 } if [ "$1" = "--restore" ]; then restore fi WALLPAPER="$1" [ -f "$WALLPAPER" ] || { echo "图片不存在: $WALLPAPER"; exit 1; } for cmd in gresource glib-compile-resources; do command -v "$cmd" >/dev/null 2>&1 || { echo "缺少 $cmd, 请先: sudo apt install libglib2.0-bin" exit 1 } done WORK_DIR=$(mktemp -d) trap 'rm -rf "$WORK_DIR"' EXIT # 1. 只保留第一份原始备份, 多次运行不会互相覆盖 if [ ! -f "$BACKUP" ]; then sudo cp "$GRESOURCE" "$BACKUP" fi # 2. 导出全部资源, 并同步生成编译用的 XML XML="$WORK_DIR/gnome-shell-theme.gresource.xml" { echo '<?xml version="1.0" encoding="UTF-8"?>' echo '<gresources>' echo " <gresource prefix=\"$PREFIX\">" while IFS= read -r res; do rel="${res#$PREFIX/}" mkdir -p "$WORK_DIR/$(dirname "$rel")" gresource extract "$GRESOURCE" "$res" > "$WORK_DIR/$rel" echo " <file>$rel</file>" done < <(gresource list "$GRESOURCE") echo ' </gresource>' echo '</gresources>' } > "$XML" # 3. 压缩并放入新背景图 (只缩小不放大, 默认最长边 1920) MAX_W="${MAX_W:-1920}" QUALITY="${QUALITY:-85}" if command -v convert >/dev/null 2>&1; then convert "$WALLPAPER" -resize "${MAX_W}x${MAX_W}>" \ -strip -quality "$QUALITY" "$WORK_DIR/login-background.jpg" else cp "$WALLPAPER" "$WORK_DIR/login-background.jpg" fi sed -i "s| </gresource>| <file>login-background.jpg</file>\n </gresource>|" "$XML" # 4. 用 python 重写 #lockDialogGroup, sed 跨行处理 CSS 块太脆 python3 <<PY import re, sys css_path = "$WORK_DIR/gnome-shell.css" css = open(css_path, encoding="utf-8").read() new_block = ('#lockDialogGroup {\n' ' background: #111111 url("resource:///org/gnome/shell/theme/login-background.jpg");\n' ' background-repeat: no-repeat;\n' ' background-size: cover;\n' ' background-position: center;\n' '}') css, n = re.subn(r'#lockDialogGroup\s*\{[^}]*\}', new_block, css, flags=re.S) open(css_path, "w", encoding="utf-8").write(css) print(f"替换了 {n} 处 #lockDialogGroup") if n == 0: print("没有匹配到 #lockDialogGroup, CSS 结构可能变了, 停止编译", file=sys.stderr) sys.exit(1) PY # 5. 编译到临时文件再覆盖, 避免写一半损坏系统文件 glib-compile-resources --sourcedir="$WORK_DIR" \ --target="$WORK_DIR/out.gresource" "$XML" sudo cp "$WORK_DIR/out.gresource" "$GRESOURCE" sudo chown root:root "$GRESOURCE" sudo chmod 644 "$GRESOURCE" sudo systemctl restart gdm3 echo "完成。登录界面背景已替换为 $WALLPAPER"脚本分成五步,逻辑很直白。第 2 步是整段的关键:gresource list拿到全部资源路径,循环里逐个 extract 到临时目录,同时把文件名写进 XML。因为编译是白名单模式,这一步偷懒少一个文件,新包里就少一个资源,所以必须全量导出、全量写入,一个都不能漏。
第 3 步的-resize 1920x1920>表示只缩小不放大,>号是 ImageMagick 的「仅当大于目标时才缩放」语法;-strip去掉 EXIF 信息,-quality 85控制 jpg 压缩比。选 jpg 而不是 png 是因为体积小、解码快,登录界面加载时对性能更友好。随后sed把新图片补进 XML。
第 4 步用 python 而不是 sed 改 CSS,是因为#lockDialogGroup规则块跨多行且缩进不固定,sed 按行替换会在 Yaru 主题更新缩进时翻车。regex 里的re.S让点号能匹配换行,整个规则块一次性替换。如果没匹配到目标选择器,脚本直接退出,不会出现「改了但没生效」的假成功。
第 5 步先编译到临时文件再cp覆盖,而不是用--target直接写系统路径,是为了防止编译中断时留下半个文件把 GDM 搞崩。chown root:root和chmod 644保证 gdm 用户有读权限,这属于备份之外的另一个安全网。
3.3 脚本里 4 个值得改的参数
| 参数/变量 | 默认值 | 作用 | 建议 |
|---|---|---|---|
| MAX_W | 1920 | 新背景图的最长边像素 | 4K 显示器可设 2560,别超过原图分辨率 |
| QUALITY | 85 | 转 jpg 的质量 | 80~90,低于 80 会有可见噪点 |
| BACKUP 路径 | gresource.orig | 首次备份的固定文件名 | 保持默认,--restore依赖它 |
| GDM 服务名 | gdm3 | 重启的服务 | 换登录器脚本不适用 |
传参方式是用环境变量前缀,例如sudo MAX_W=2560 QUALITY=90 bash ubuntu-login-bg.sh img.jpg,不需要改脚本内容。注意 22.04 默认装的是 ImageMagick 6,命令是convert;如果你自己装了 ImageMagick 7,命令变成了magick,要么建一个convert的软链,要么把脚本里的 convert 换成 magick。
注意:
--restore恢复的是第一次运行脚本时的原始备份,因为脚本只在 BACKUP 不存在时才创建。想回滚到某次修改前的状态,需要提前手动sudo cp一份当时的 gresource。
4. 登录背景修改避坑指南:5 个实踩过的坑
脚本能跑通不等于不会翻车,下面 5 个坑按出现频率排,每条都是现象、原因、解决的顺序,我全都在 22.04 上实打实遇过。
4.1 重启 GDM 把当前桌面会话踢没了
现象:在图形桌面里直接运行sudo systemctl restart gdm3,屏幕一黑回到登录框,正在编辑的文档全部丢失。
原因:GDM 是登录管理器,restart 会把托管的整个用户会话一起结束,这不是脚本 bug,而是服务本身的语义。图形会话里跑的 shell 命令也会随之中断。
解决:脚本里的DISPLAY检查会在图形会话内弹出确认,拦掉大半误操作。但真正安全的流程是:保存所有工作 → Ctrl+Alt+F3 切到 tty → 在 tty 登录后运行脚本 → 完成后 Ctrl+Alt+F1 回图形登录。注意从 tty 跑同样会结束图形会话,切 tty 的意义在于 GDM 万一起不来时,你还有一个能手动恢复的命令行入口——这是血泪经验,GDM 挂了而手里没有 tty 才是最绝望的。
4.2 手写 XML 只留两行资源,登录界面图标全丢
现象:登录界面能起来,但顶部面板图标、关机按钮、日历图标全部变成空白方块,像是主题半残。
原因:编译是白名单模式。如果你手写 XML 只列了gnome-shell.css和login-background.jpg两个文件,其他 svg/png 全部不会进入新 gresource,主题里所有resource:///org/gnome/shell/theme/xxx.svg引用全部 404。
解决:永远用gresource list循环导出并同步生成 XML,而不是手写文件清单。第 3.2 节的脚本就是这么做的。改完可以用gresource list数一下文件数量,和修改前对比,数量一致才算完整。
4.3 壁纸 10MB 高清图,登录画面肉眼可见的卡
现象:换了一部手机拍的 4000x3000 原图,锁屏界面出来慢了三秒,呼出密码框时也能感到掉帧。
原因:gnome-shell 在进入锁屏时才解码背景图,10MB 以上的 JPEG/PNG 解码耗时且占内存;而 gresource 是整体映射进内存的,大图会拖慢 GDM 启动。
解决:用convert预先缩小到 1920 长边并压到 quality 85,壁纸文件控制在 2MB 以内。4K 显示器可以放宽到 2560,但不要超过原图分辨率,否则会浪费解码时间却没有画质收益。桌面壁纸可以任性,登录背景不值得拿流畅度去换。
4.4 升级 gnome-shell 后背景又变回默认
现象:某次sudo apt upgrade之后,登录背景毫无征兆地回到默认主题。
原因:包更新时gnome-shell或ubuntu-session会重新安装 gresource,把自定义文件覆盖掉。这是包管理器的正常行为,不是脚本失效。
解决:不要指望一次修改管终身。把脚本和原图归档到固定位置,升级后重跑一次:sudo bash /usr/local/bin/ubuntu-login-bg.sh /usr/local/share/login-backgrounds/current.jpg。大版本升级(22.04 → 24.04)后路径可能变化,脚本里的find_gresource会自动定位新位置,但最好先跑一次ls确认。
4.5 CSS 明明改对了却不生效:没重启 GDM 或没检查替换结果
现象:gresource文件时间戳已经变了,extract 出来看 CSS 也对,但登录背景还是旧的。
原因:三种可能叠在一起。一是只锁屏没重启 GDM,运行中的 gnome-shell 还持有旧资源;二是新 gresource 权限不对,gdm 用户读不了,GDM 静默回退默认主题;三是编译阶段实际失败但被忽略了(比如手动执行时没加set -e)。
解决:改完必须systemctl restart gdm3,锁屏界面和 GDM 用的是同一个 gnome-shell 进程,资源加载后就固定了。然后检查ls -l /usr/share/gnome-shell/gnome-shell-theme.gresource应该是root:root且权限 644。最后用下面的命令对比资源数量:
gresource list /usr/share/gnome-shell/gnome-shell-theme.gresource | wc -l journalctl -u gdm3 --since today | grep -iE 'error|fail'5. 验证脚本成果的三个习惯,和一条「升级后悔药」路径
5.1 三条命令验收登录背景
脚本跑完别急着庆祝,先确认新背景真的进了资源包:
sudo gresource list /usr/share/gnome-shell/gnome-shell-theme.gresource | grep login-background应该能看到login-background.jpg而不是原来的文件名。再看 CSS 规则是否写对:
sudo gresource extract /usr/share/gnome-shell/gnome-shell-theme.gresource \ /org/gnome/shell/theme/gnome-shell.css | grep -A5 '#lockDialogGroup'输出里应该有background-size: cover和 jpg 的 resource URI。这两条过了,再重启 GDM 看实际效果。
5.2 升级后重跑:把脚本当成随版本走的配置
我现在的习惯是:把原图归档到/usr/local/share/login-backgrounds/current.jpg,脚本放在/usr/local/bin/ubuntu-login-bg.sh,每次升级完 gnome-shell 相关包就重跑一次。两分钟的事,换来的是登录界面永远是你想要的样子。
最后留一条后悔药路径:如果哪天看腻了想还原,sudo bash ubuntu-login-bg.sh --restore一条命令回到最初;如果 GDM 起不来,切到 tty,手动把gnome-shell-theme.gresource.orig复制回去再systemctl restart gdm3,这套组合拳我验证过不止一次。把脚本当配置项而不是一次性补丁来维护,是我在这件事上最大的教训。希望帮到你。
本文还有配套的精品资源,点击获取