修复 DNF/RPM 在从 img 拷贝后运行崩溃的问题

dnf update
Repository OS is listed more than once in the configuration
Repository everything is listed more than once in the configuration
Repository EPOL is listed more than once in the configuration
Repository debuginfo is listed more than once in the configuration
Repository source is listed more than once in the configuration
Repository update is listed more than once in the configuration
Repository update-source is listed more than once in the configuration
OS                                                                                                                          22 kB/s | 2.7 kB     00:00
everything                                                                                                                  28 kB/s | 2.8 kB     00:00
EPOL                                                                                                                        27 kB/s | 2.8 kB     00:00
debuginfo                                                                                                                   27 kB/s | 2.8 kB     00:00
source                                                                                                                      26 kB/s | 2.7 kB     00:00
update                                                                                                                      21 kB/s | 2.3 kB     00:00
update-source                                                                                                               22 kB/s | 2.7 kB     00:00
/usr/include/c++/10.3.1/bits/basic_string.h:1094: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::reference std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::front() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::reference = char&]: Assertion '!empty()' failed.
Aborted (core dumped)

本文记录了在从挂载的 rootfs.img 使用脚本/cp -af 重建文件系统后,dnf 报错并崩溃(C++ 断言 Assertion '!empty()')的排查与修复过程。


问题概述

  • 症状:在通过挂载 img 并用脚本或 cp -arf 拷贝 rootfs 后,执行 dnf update 会出现仓库重复警告(Repository ... is listed more than once)并抛出 C++ 断言 Assertion '!empty()' failed,导致 dnf 崩溃。
  • 对比场景:直接烧录原始 img 到设备时不会出现问题;只有通过挂载并拷贝重建的 rootfs 会复现。

根因分析

  1. 元数据丢失(xattrs / ACL / SELinux)
    • cpgit 都不会保留文件的扩展属性(xattrs)、ACL、以及 SELinux 标签(ls -Z 可见)。
    • dnf / rpm 在读取数据库或配置时依赖这些元数据,丢失会导致访问失败或读取到空内容,触发断言。
  2. 配置与数据库不一致
    • 只同步了数据库目录(/var/lib/rpm/var/lib/dnf),却没有同步配置目录(/etc/yum.repos.d/etc/dnf)。数据库和配置不匹配或配置被损坏,会造成解析失败。
  3. 脚本破坏文件权限/所有权
    • 脚本中若存在 chown -R root:root ... 等全局所有权变更,会破坏特殊文件的所有权与 setuid/setgid 位,导致运行时错误。

设计原则与修复思路

  • 保持整体拷贝速度(使用 cp -af),但对关键目录采用能保留元数据的方式进行恢复(rsync -axHAXtar --xattrs)。
  • 在 QEMU 中调试的运行时状态(数据库 + 配置)通过 tar 打包导出,tar 能保留 xattrs/SELinux/ACL,Git 只跟踪该 tar 包(避免仓库膨胀与元数据丢失)。
  • 构建阶段优先检测导出的 tar 包并解压恢复,解压前先清理目标目录,避免旧文件干扰。

关键命令

  • 从镜像手动挂载并打包:
sudo mount rootfs.img /mnt/rootfs
sudo tar --xattrs --xattrs-include='*' --acls --selinux -czf rpm_db.tar.gz \
  -C /mnt/rootfs var/lib/rpm var/lib/dnf etc/yum.repos.d etc/dnf
sudo umount /mnt/rootfs
  • 构建时恢复:
sudo rm -rf ${ROOTFS_DIR}/var/lib/rpm ${ROOTFS_DIR}/var/lib/dnf ${ROOTFS_DIR}/etc/yum.repos.d ${ROOTFS_DIR}/etc/dnf
sudo tar --xattrs --xattrs-include='*' --acls --selinux -xf rpm_db.tar.gz -C ${ROOTFS_DIR}/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

交叉编译之王 hahaha

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值