我想要编写的脚本是这样的:
if [ uname -r is not == highest version of kernel RPM installed ]
then
echo "You need to reboot to use the latest kernel"
fi
问题是,如果 的输出rpm -q kernel
类似于:
kernel-2.6.32-358.10.2.el6.x86_64
kernel-2.6.32-358.6.1.el6.x86_64
…我如何确定哪个更高?我知道简单的字符串排序是不可靠的(在这个例子中它将是向后的)。 rpm 有捷径吗?还是我必须自己解析所有内容并进行比较?
答案1
长话短说
第三次尝试确实有效!我将留下前两次尝试,以便将来可能遇到此问答的其他人希望能够深入了解解析 RPM 版本信息并确定第一、第二的沿袭是多么重要的问题, ETC。
尝试#1(OP说没用)
此命令将对输出进行排序并按版本顺序提供它们:
$ rpm -q kernel --queryformat "%{VERSION} %{RELEASE}\n"|sort -n
2.6.18 238.12.1.el5
2.6.18 238.19.1.el5
2.6.18 274.12.1.el5
2.6.18 308.8.2.el5
为什么它不起作用:天真的人会认为您可以使用该sort
命令的某些变体来执行此任务,但给定 RPM 的实际版本信息的格式存在足够的可变性和不一致,因此它无法胜任该任务。
尝试#2(OP说没用)
$ rpm -q --last kernel | head -n 1 | cut -d' ' -f1
kernel-2.6.35.14-106.fc14
为什么它不起作用:我非常希望这种方法能够产生 OP 正在寻找的结果,但正如 @Joel 在评论中指出的那样,这个方法的问题是,开关--last
只是返回按 RPM 安装日期排序的结果。
尝试#3
这个肯定能完成这项工作。我发现了一套名为 RPM 开发工具的工具。该套件中有 2 个工具,使您能够确定 RPM 的一个版本是否比另一个版本更新或旧。
如果尚未安装 RPM,您可以执行以下操作:
yum install rpmdevtools
第一个有用的工具称为rpmdev-vercmp
。该工具可以比较 2 个 RPM 名称并告诉您哪一个较新。例如:
$ rpmdev-vercmp kernel-2.6.35.14-100.fc14.x86_64 kernel-2.6.35.14-103.fc14.x86_64
0:kernel-2.6.35.14-103.fc14.x86_64 is newer
找到这个之后,我准备编写一个 shell 脚本,但后来意识到,我很懒,所以我又花了几分钟,发现了套件中的另一个工具,名为rpmdev-sort
.
这个工具是付费的。您可以按如下方式使用它:
$ rpm -q kernel | rpmdev-sort
kernel-2.6.35.14-100.fc14.x86_64
kernel-2.6.35.14-103.fc14.x86_64
kernel-2.6.35.14-106.fc14.x86_64
RPM 开发工具中有很多工具可能值得其他人看看,因此我将它们列在这里以供将来参考。
$ rpm -q --queryformat '[%{NAME} %{FILEMODES:perms} %{FILENAMES}\n]' rpmdevtools \
| grep -E "^.* -..x..x..x " \
| awk '{print $3}' \
| sed 's#/usr/bin/##' \
| paste - - - \
| column -t
annotate-output checkbashisms licensecheck
manpage-alert rpmargs rpmdev-bumpspec
rpmdev-checksig rpmdev-cksum rpmdev-diff
rpmdev-extract rpmdev-md5 rpmdev-newinit
rpmdev-newspec rpmdev-packager rpmdev-rmdevelrpms
rpmdev-setuptree rpmdev-sha1 rpmdev-sha224
rpmdev-sha256 rpmdev-sha384 rpmdev-sha512
rpmdev-sort rpmdev-sum rpmdev-vercmp
rpmdev-wipetree rpmelfsym rpmfile
rpminfo rpmls rpmpeek
rpmsodiff rpmsoname spectool
#3 的替代方案
OP 在评论中提到的另一种选择是使用sort -V
.那是一个资本-V
。我也从未听说过这个开关。从sort
手册页:
-V, --version-sort
natural sort of (version) numbers within text
事实证明,sort
它确实提供了对版本号进行排序的工具,因此您也可以像这样执行排序:
$ rpm -q kernel | sort -V
kernel-2.6.35.14-100.fc14.x86_64
kernel-2.6.35.14-103.fc14.x86_64
kernel-2.6.35.14-106.fc14.x86_64
答案2
您确实需要使用 RPM 库才能获得良好的结果。版本比较算法……绝对复杂。在 shell 中重新实现并不简单,但如果你可以使用 Python 进行实际比较,它就会变得相对简单。看https://stackoverflow.com/questions/3206319/how-do-i-compare-rpm-versions-in-python有关如何执行此操作的示例。
答案3
rpm -q kernel --queryformat="%{buildtime}\t%{name}-%{version}-%{release}.%{arch}\n" | sort -nr | head -1 | cut -f2
我认为按构建时间排序不太可能出现失败的极端情况,这与安装时间不同。然而,--last 更简洁。
答案4
--last
不会告诉您最高版本号,但会按安装日期排序。这样你就可以看到最近安装的版本:
[root@xms_apps ~]# rpm -qa kernel-xen --last
kernel-xen-2.6.18-348.1.1.el5 Tue 29 Jan 2013 02:18:52 PM EST
kernel-xen-2.6.18-308.11.1.el5 Fri 20 Jul 2012 04:00:26 PM EDT
kernel-xen-2.6.18-308.8.2.el5 Wed 20 Jun 2012 03:32:47 PM EDT
大多数时候(除非他们手动安装内核)两者应该是相同的。
为了在 100% 的时间内 100% 正确,您必须将两个内核版本进行格式化,2.6.*
然后从 2.6 之后开始将其分解(RHEL 不会在单个版本中大幅重新设置基础,RHEL5将始终是 2.6 内核),只需迭代 rpm 输出的每一行(可能按--last
性能排序),并将每个位置与您获得的内核版本中的类似位置进行比较(uname -r
如果 rpm 数据库字符串中的任何数字更大)比 uname 字符串,立即退出并显示该消息。
为了帮助你,有一个类似的问题在这里问。但是该函数假设纯点分十进制表示法,因此您可以比较连字符前的数字位置(因为只有一个),然后使用该人的 bash 函数来测试补丁版本是否高于uname
rpm db 字符串中的版本。