admin 管理员组

文章数量: 1184232

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
source26 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)
    • cp git 都不会保留文件的扩展属性(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 -axHAX tar --xattrs )。
  • 在 QEMU 中调试的运行时状态(数据库 + 配置)通过 tar 打包导出, tar 能保留 xattrs/SELinux/ACL,Git 只跟踪该 tar 包(避免仓库膨胀与元数据丢失)。
  • 构建阶段优先检测导出的 tar 包并解压恢复,解压前先清理目标目录,避免旧文件干扰。

关键命令

  • 从镜像手动挂载并打包:
sudomount rootfs.img /mnt/rootfs
sudotar --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
sudoumount /mnt/rootfs
  • 构建时恢复:
sudorm -rf ${ROOTFS_DIR}/var/lib/rpm ${ROOTFS_DIR}/var/lib/dnf ${ROOTFS_DIR}/etc/yum.repos.d ${ROOTFS_DIR}/etc/dnf
sudotar --xattrs --xattrs-include='*' --acls --selinux -xf rpm_db.tar.gz -C ${ROOTFS_DIR}/

本文标签: 系统 彻底清除 编程