Ai助手
Home/Linux / 移除套件誤卸載RPM造成了dnf及rpm及yum皆不正常

AlmaLinux / CentOS 9 — 修復誤刪 RPM 套件導致 DNF 與 RPM 無法運作的完整復原紀錄

主機環境:AlmaLinux 9.6 (Sage Margay)
日期:2025-10-04


一、問題背景

在一次誤操作中,系統核心的 RPM 套件管理元件(rpm / rpm-libs / rpm-build-libs) 被移除或破壞,導致:

  • dnf 執行報錯: ImportError: cannot import name 'ts' from 'rpm._rpm'
  • rpm 無法使用、甚至不存在 /usr/bin/rpm
  • dnf 顯示: error: no dbpath has been set error: cannot open Packages database in /%{_dbpath}
  • 系統套件管理完全中斷,無法安裝、更新或重建資料庫。
(base) [root@khmail ~]# dnf
error: Unable to open /usr/lib/rpm/rpmrc for reading: 沒有此一檔案或目錄.
Traceback (most recent call last):
File "/usr/bin/dnf", line 61, in
from dnf.cli import main
File "/usr/lib/python3.9/site-packages/dnf/init.py", line 30, in
import dnf.base
File "/usr/lib/python3.9/site-packages/dnf/base.py", line 32, in
from dnf.comps import CompsQuery
File "/usr/lib/python3.9/site-packages/dnf/comps.py", line 27, in
from dnf.exceptions import CompsError
File "/usr/lib/python3.9/site-packages/dnf/exceptions.py", line 22, in
import dnf.util
File "/usr/lib/python3.9/site-packages/dnf/util.py", line 30, in
import dnf.callback
File "/usr/lib/python3.9/site-packages/dnf/callback.py", line 22, in
import dnf.yum.rpmtrans
File "/usr/lib/python3.9/site-packages/dnf/yum/rpmtrans.py", line 26, in
import rpm
File "/usr/lib64/python3.9/site-packages/rpm/init.py", line 39, in
from rpm.transaction import *
File "/usr/lib64/python3.9/site-packages/rpm/transaction.py", line 3, in
from rpm._rpm import ts as TransactionSetCore
ImportError: cannot import name 'ts' from 'rpm._rpm' (/usr/lib64/python3.9/site-packages/rpm/_rpm.cpython-39-x86_64-linux-gnu.so)


二、初步檢查與環境狀態

  1. 檢查 RPM 主程式是否存在: which rpm → 無結果。
  2. 檢查 RPM Python 模組: python3 -c "import rpm" → 報 ImportError: cannot import name 'ts',顯示底層 .so 模組損毀。
  3. 確認 /usr/lib64/lib*rpm*.so* 等關鍵檔案缺失。

三、採取的修復步驟

1️⃣ 手動下載 RPM 套件

從 AlmaLinux 官方鏡像站下載:

http://repo.almalinux.org/almalinux/9/BaseOS/x86_64/os/Packages/

必要套件:

  • rpm-4.16.1.3-37.el9.x86_64.rpm
  • rpm-libs-4.16.1.3-37.el9.x86_64.rpm
  • rpm-build-libs-4.16.1.3-37.el9.x86_64.rpm
  • (輔助)lua-libs-5.4.4-4.el9.x86_64.rpm, zstd-1.5.1-2.el9.x86_64.rpm, ima-evm-utils

2️⃣ 使用 Python 手動解壓 RPM 檔案

由於可能會某些套件移除系統缺乏 rpm2cpiobsdtar 等工具,
使用 Python 直接分析 .rpm 檔案內的 zstd payload:

import os, re, subprocess
rpm_path = "/tmp/rpm-libs-4.16.1.3-37.el9.x86_64.rpm"
out_dir = "/tmp/rpm_extract"
os.makedirs(out_dir, exist_ok=True)
data = open(rpm_path, "rb").read()

m = re.search(b'\x28\xB5\x2F\xFD', data)
payload = data[m.start():]
open(out_dir + "/payload.cpio.zst", "wb").write(payload)
os.system(f"cd {out_dir} && unzstd payload.cpio.zst && cpio -idmv < payload.cpio")

完成後,獲得解壓內容:

./usr/lib64/librpm.so.9
./usr/lib64/librpmio.so.9
./usr/bin/rpm

建議可以先下載cpio 以利解壓縮 cpio-2.13-16.el9.x86_64.rpm

python3 - <<'PYCODE'
import os, subprocess

rpm_file = "/tmp/cpio-2.13-16.el9.x86_64.rpm"
out_dir = "/tmp/rpm_build_libs_extract"
os.makedirs(out_dir, exist_ok=True)

print(f"📦 正在解析 {rpm_file} ...")
with open(rpm_file, "rb") as f:
    data = f.read()

# 直接掃描 zstd magic bytes (28 B5 2F FD)
magic = b"\x28\xB5\x2F\xFD"
offset = data.find(magic)
if offset == -1:
    print("❌ 找不到 ZSTD 壓縮段,RPM 檔可能損壞或不是 zstd 格式")
    raise SystemExit(1)

payload = data[offset:]
out_zst = f"{out_dir}/payload.cpio.zst"
with open(out_zst, "wb") as f:
    f.write(payload)

print(f"✅ 找到 zstd 段落,位於 offset={offset}, 輸出 {out_zst}")

# 解壓縮
os.system(f"cd {out_dir} && unzstd payload.cpio.zst && cpio -idmv < payload.cpio")

print("✅ 已完成 rpm-build-libs 解壓至 /tmp/rpm_build_libs_extract")
PYCODE


3️⃣ 覆蓋修復關鍵檔案

將提取的檔案覆蓋回系統:

cp -av rpm-4.16.1.3-37.el9.x86_64/usr/bin/rpm /usr/bin/
cp -av rpm-libs-4.16.1.3-37.el9.x86_64/usr/lib64/librpm*.so* /usr/lib64/
cp -av rpm-build-libs-4.16.1.3-37.el9.x86_64/usr/lib64/librpmbuild*.so* /usr/lib64/
ldconfig

檢查:

rpm --version
# ➜ RPM version 4.16.1.3

4️⃣ 修正 /usr/lib/rpm/rpmrc 內容格式錯誤

原檔案中 dbpath:/var/lib/rpm 應為空白分隔:

cat >/usr/lib/rpm/rpmrc <<'EOF'
macrofiles: /usr/lib/rpm/macros:/usr/lib/rpm/%{_target}/macros:/etc/rpm/macros.*:/etc/rpm/macros:/etc/rpm/%{_target}/macros:~/.rpmmacros
optflags: x86_64 -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection
buildarchtranslate: noarch: noarch
buildarchtranslate: x86_64: x86_64
dbpath /var/lib/rpm
EOF

5️⃣ 重建 RPM 資料庫

cd /var/lib/rpm
rm -f __db*
rpmdb --rebuilddb

驗證:

rpm -qa | head

✅ 可成功列出套件。


6️⃣ 驗證 DNF 回復

/usr/bin/dnf --version
# ➜ 4.14.0
dnf list kernel
# ➜ 正常顯示可用版本

四、問題根源與教訓

問題點說明
誤刪 RPM 相關核心庫rpm 核心元件 (/usr/bin/rpm、librpm.so、librpmbuild.so)導致系統無法管理套件,dnfrpm 同時損毀
rpmrc 沒有檔案(或/usr/lib/rpm/macros 沒有檔案)
[root@khmail fixrpm_full]# rpm -qa | head
error: bad option ‘dbpath’ at (null):5
error: no dbpath has been set
error: cannot open Packages database in /%{_dbpath}
(base) [root@khmail fixrpm_full]#
造成無法找到 dbpath:
可以利用上述下戴相關linux rpm- 包,來解壓縮後找到
缺乏 rpm2cpio / bsdtar需改用 Python 分析 RPM header 直接提取 payload
rpmdb 損毀透過 rpmdb --rebuilddb 成功重建

五、恢復後建議

  1. 立即備份 RPM 相關核心: mkdir -p /root/rpm_backup cp -a /usr/bin/rpm /usr/lib64/librpm*.so* /usr/lib/rpm/rpmrc /root/rpm_backup/
  2. 啟用 DNF 自動修復插件dnf install dnf-plugins-core -y
  3. 建立自動快照或快照卷(如使用 LVM / Btrfs)。
  4. 若未來系統升級、請避免同時移除 rpmdnf

六、最終狀態確認

rpm --version
# RPM version 4.16.1.3

/usr/bin/dnf --version
# 4.14.0

rpm -qa | head
# (成功列出系統套件清單)

🎯 系統已完全修復。在linux上我們常利用管理

AI自主客戶服務

若有任何需求可以直接詢問專業AI客服

24小時


留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *