清除 yum 失败后遗留的重复组件
1. 问题
假若 yum 在更新时发生严重错误例如:ssh 对话在更新时断线,yum 由于内存不足而终止,系统失去电源等,你的系统有可能会停留在一个不确定的状态,并出现两组组件。到时候 yum-complete-transaction 及任何 yum 更新都会拒绝执行并投诉有重复组件。
2. 修正概述
你必须进行手动修复来修正这个问题。在开始之先,我们极力推荐你最少将 /var/lib/rpm 及 /var/lib/yum 备份,那么就算在尝试修复的过程中系统毁坏得 更严重 时,你仍可以恢复到现有的状况。
更新信息:看来由 7.6 版开始 package-cleanup 指令新增了一个选项: --removenewestdupes 正正能做到本篇文章尝试以人手进行的任务。请先以 package-cleanup --cleandupes --removenewestdupes 作为第一步,然后才继续以下步骤。要是该选项不获接纳,你也许要执行下列指引。否则所须的事情应该已经办妥,而你可以重新执行 yum update,但今次不要再切断电源/停用终端機……
3. 旧修正信息 —— 大概已不再需要
这里的程序会创建一个重复组件的清单。利用这个清单,我们 单单 从数据库删除较新组件的记录。之后,我们便重新执行 yum update 下载新组件及再次更新系统,这样可确保新版的组件被完全地及正确地安装。
4. 修正详情
package-cleanup 指令是 yum-utils 组件的一部份,因此你首先要安装该组件。安装后,执行 package-cleanup --dupes --noplugins 便会输出类似以下的清单,它是我在一台虚拟计算机更新中途「拔掉电源」后所产生的:
[root@localhost ~]# package-cleanup --dupes Loaded plugins: fastestmirror nss-tools-3.28.4-8.el7.x86_64 nss-tools-3.28.4-15.el7_4.x86_64 grub2-common-2.02-0.64.el7.centos.noarch grub2-common-2.02-0.65.el7.centos.2.noarch wpa_supplicant-2.6-5.el7.x86_64 wpa_supplicant-2.6-5.el7_4.1.x86_64 grub2-tools-extra-2.02-0.65.el7.centos.2.x86_64 grub2-tools-extra-2.02-0.64.el7.centos.x86_64 nss-sysinit-3.28.4-15.el7_4.x86_64 nss-sysinit-3.28.4-8.el7.x86_64 grub2-tools-2.02-0.65.el7.centos.2.x86_64 grub2-tools-2.02-0.64.el7.centos.x86_64 bind-license-9.9.4-50.el7.noarch bind-license-9.9.4-51.el7.noarch nss-3.28.4-15.el7_4.x86_64 nss-3.28.4-8.el7.x86_64 kmod-20-15.el7_4.4.x86_64 kmod-20-15.el7.x86_64 systemd-219-42.el7.x86_64 systemd-219-42.el7_4.4.x86_64 selinux-policy-3.13.1-166.el7_4.5.noarch selinux-policy-3.13.1-166.el7.noarch grub2-pc-modules-2.02-0.65.el7.centos.2.noarch grub2-pc-modules-2.02-0.64.el7.centos.noarch NetworkManager-libnm-1.8.0-11.el7_4.x86_64 NetworkManager-libnm-1.8.0-9.el7.x86_64 NetworkManager-1.8.0-11.el7_4.x86_64 NetworkManager-1.8.0-9.el7.x86_64 nss-softokn-freebl-3.28.3-6.el7.x86_64 nss-softokn-freebl-3.28.3-8.el7_4.x86_64 grub2-pc-2.02-0.65.el7.centos.2.x86_64 grub2-pc-2.02-0.64.el7.centos.x86_64 openssh-server-7.4p1-13.el7_4.x86_64 openssh-server-7.4p1-11.el7.x86_64 systemd-libs-219-42.el7_4.4.x86_64 systemd-libs-219-42.el7.x86_64 cpio-2.11-24.el7.x86_64 cpio-2.11-25.el7_4.x86_64 kmod-libs-20-15.el7.x86_64 kmod-libs-20-15.el7_4.4.x86_64 ncurses-libs-5.9-13.20130511.el7.x86_64 ncurses-libs-5.9-14.20130511.el7_4.x86_64 nss-softokn-3.28.3-8.el7_4.x86_64 nss-softokn-3.28.3-6.el7.x86_64 ncurses-base-5.9-14.20130511.el7_4.noarch ncurses-base-5.9-13.20130511.el7.noarch bash-4.2.46-29.el7_4.x86_64 bash-4.2.46-28.el7.x86_64 NetworkManager-wifi-1.8.0-9.el7.x86_64 NetworkManager-wifi-1.8.0-11.el7_4.x86_64 kexec-tools-2.0.14-17.2.el7.x86_64 kexec-tools-2.0.14-17.el7.x86_64 NetworkManager-tui-1.8.0-11.el7_4.x86_64 NetworkManager-tui-1.8.0-9.el7.x86_64 openssh-7.4p1-11.el7.x86_64 openssh-7.4p1-13.el7_4.x86_64 grub2-tools-minimal-2.02-0.64.el7.centos.x86_64 grub2-tools-minimal-2.02-0.65.el7.centos.2.x86_64 NetworkManager-team-1.8.0-11.el7_4.x86_64 NetworkManager-team-1.8.0-9.el7.x86_64 systemd-sysv-219-42.el7_4.4.x86_64 systemd-sysv-219-42.el7.x86_64 binutils-2.25.1-32.base.el7_4.1.x86_64 binutils-2.25.1-31.base.el7.x86_64 selinux-policy-targeted-3.13.1-166.el7_4.5.noarch selinux-policy-targeted-3.13.1-166.el7.noarch
持著这份清单,你必须从 rpm 数据库删除每对重复组件中的 较新版 ,好让它认为旧版组件仍在系统上。package-cleanup 中有一个 --cleandupes 的选项,但它与安全做法刚刚相反,并且删除旧版组件。问题是你不能确定新版组件的安装是否正确,因此删除旧记录虽然能修正重复组件的问题,却不能保证你的系统是稳定的。
你可以利用 rpm -e --justdb --nodeps $newerpackage 来删除重复的组件 —— 就上述样例而言,指令是 rpm -e --justdb --nodeps nss-tools-3.28.4-15.el7_4.x86_64 grub2-common-2.02-0.65.el7.centos.2.noarch wpa_supplicant-2.6-5.el7_4.1.x86_64 etc etc(请勿盲目地剪贴这个指令,你的组件与版本将会有异)。
5. 潜在问题
请留意较新的组件 不一定 在清单中较迟出现 —— 就好像 selinux-policy-targeted-3.13.1-166.el7_4.5.noarch 是首先被列出的,而它比重复了的 selinux-policy-targeted-3.13.1-166.el7.noarch 还要新 ,而 NetworkManager-1.8.0-11.el7_4.x86_64 比 NetworkManager-1.8.0-9.el7.x86_64 还要新 。因此要将这个步骤自动化并不简单,而你必须以手动方式创建这个清单……抱歉!
一个较为方便的做法是将 package-cleanup 的输出导入文本,然后利用你惯用的编辑器把 较旧版 的组件名称从清单中删除,只剩下较新版的组件名称。做法:package-cleanup --dupes --noplugins > pcd.txt 然后编辑它,从清单中删除旧版本,存储它,然后执行 for p in $(cat pcd.txt); do echo rpm -e --justdb --nodeps $p;done。细心的读者会发现这样做只会在终端機打印要执行的指令……你必须去除 echo 才会真正 执行 这些指令。你有责任确保这些指令将会做你所期望的事情,如果出错的话请勿怪责我!
现在你明白在开始前把 /var/lib/yum 和 /var/lib/rpm 备份的重要性了……你 有 把它们备份,对吗?
去除所有重复的组件后,现在你可以重新执行 yum update,但你亦须要修正导致上次更新出错的原因。要是你通过 ssh 进行更新,但连接有可能被中断,你可利用 tmux 或 screen 防止 yum 在断线时被终止。要是你内存不足,增添内存或调换档,或在开始前先停止占用大量内存的进程。
Translation of revision 9