Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

What I want to script is something along the lines of:

if [ uname -r is not == highest version of kernel RPM installed ]
then
  echo "You need to reboot to use the latest kernel"
fi

The problem is, if the output of rpm -q kernel is something like:

kernel-2.6.32-358.10.2.el6.x86_64
kernel-2.6.32-358.6.1.el6.x86_64

… how do I determine which is higher? I know a simple string sort is not reliable (it will be backwards with this example). Is there a shortcut with rpm or do I have to parse out everything and compare it myself?

share|improve this question
    
You can use /var/log/yum.log for that. Or 'ls -lht /boot | grep vmlinuz' if the kernel is what you're interested in. –  schaiba May 21 '13 at 16:12
    
Those are not reliable methods for determining which is a higher version. Checking /boot might include kernels that are for entirely different multiboot partitions. –  sosiouxme May 21 '13 at 16:27
    
Maybe I'm overthinking it. rpm -q kernel always seems to list kernels in version order. Is that reliable? –  sosiouxme May 21 '13 at 16:27
    
'ls -lht /boot | grep vmlinuz | grep el6' :) –  schaiba May 21 '13 at 16:41
    
And sort -V does not give correct result? –  Sukminder May 21 '13 at 23:03

3 Answers 3

up vote 3 down vote accepted

TL;DR

The 3rd attempt actually works! I'm leaving the first 2 attempts so that others that may come across this Q&A in the future will hopefully gain some insight into how non-trivial a problem it is to parse RPM version information and determine the lineage of which came first, second, etc.

Attempt #1 (OP said didn't work)

This command will sort the output and give you them in version order:

$ 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

WHY IT DIDN'T WORK: A naive person would think that you can use some variant of the sort command to perform this task, but there is enough variability and inconsistency in the formatting of the actual version information for a given RPM that it just isn't up to the task.

Attempt #2 (OP said didn't work)

$ rpm -q --last kernel | head -n 1 | cut -d' ' -f1
kernel-2.6.35.14-106.fc14

WHY IT DIDN'T WORK: I had high hopes that this approach would yield the results the OP was looking for, but the issue with this one as @Joel pointed out in the comments, is that the --last switch is merely returning the results sorted by the date the RPMs were installed.

Attempt #3

This one will definitely do the job. I found a suite of tools called RPM Development Tools. There are 2 tools in this suite that will give you the capability to determine whether one version of a RPM is newer or older than another.

If the RPM isn't already installed you can do so as follows:

yum install rpmdevtools

The first tool that's useful is called rpmdev-vercmp. This tool can compare 2 names of RPMs and tell you which one is newer. For example:

$ 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

After finding this I was all set to put together a shell script but then realized, man I'm lazy, so I poked a few minutes more and found another tool in the suite called rpmdev-sort.

This tool is pay-dirt. You can use it as follows:

$ 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

There are a lot of tools in RPM Development Tools that might be worth a look for others so I'm listing them here for future reference.

$ 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

An alternative to #3

An alternative that the OP mentioned in the comments is to use sort -V. That's a capital -V. I'd never heard of this switch either. From the sort man page:

-V, --version-sort
       natural sort of (version) numbers within text

As it turns out sort does provide a facility to sort version numbers so you could also perform the sorting like so:

$ 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
share|improve this answer
    
Sorry, I don't think so. A simple string sort would put kernel-2.6.10 before kernel-2.6.9. This has to work generically, not just for the example. –  sosiouxme May 21 '13 at 16:22
    
-n only helps you with the first number. Try sorting this: 2.6.18 238.12.1.el5 2.6.18 238.19.1.el5 2.6.18 274.12.1.el5 2.6.18 274.8.2.el5 sort is absolutely the wrong tool here, as well as anything else that doesn't know anything about version-release schemes. –  sosiouxme May 21 '13 at 17:17
    
@slm --last sorts by package installation time, it's not necessarily going to be the latest kernel (if they did a manual rpm install of a lower kernel version, for instance). –  Bratchley May 21 '13 at 19:39
    
This one is starting to feel like a dead horse 8-) –  slm May 21 '13 at 19:53
    
@sosiouxme - give my latest attempt a try, hopefully it does the job. –  slm May 25 '13 at 2:04

You really need to use the RPM library to get a good result. The version comparison algorithm is... decidedly complex. It's non-trivial to reimplement in shell, but if you can use Python to do the actual comparison, it becomes relatively straightforward. See http://stackoverflow.com/questions/3206319/how-do-i-compare-rpm-versions-in-python for an exmaple of how to do so.

share|improve this answer

--last won't tell you the highest version number but it will order by date of installation. So you can see the most recently installed version:

[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

Most of the time (unless they did a manual kernel install) the two should be the same.

To get it 100% right 100% of the time, you're going to have to get the two kernel versions down to 2.6.* format then just break it apart starting after the 2.6 (RHEL won't rebase that drastically within a single version, RHEL5 will always be a 2.6 kernel) and just iterate over each line of rpm output (possibly sorted by --last for performance) and compare each position against the analogous position in the kernel version you got from uname -r if any of the numbers are bigger in the rpm db's string than the uname string, immediately exit with that message.

To help you out there there's a similar question asked here. But that function assumes purely dotted decimal notation, so you may compare number position before the hyphen (since there's only one) then use that person's bash function to test if the patch version is higher in uname than in the rpm db string.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.