Linux kernel version comparision method

Hi All,

I am preparing a precheck script for my oracle DB installation.

I am setting an expected version value, actual version can be greater than the expected version or equal to it.

I am using the below logic to test this.

expected=2.6.32-279.el6.x86_64
received=$(uname -r)

min=$(echo -e $expected"\n"$received|sort -V|head -n 1)
if [ "$min" = "$expected" ];then
       echo "Installed Version is higher than Expected."
       echo "Passed."
else
       echo "== FAILED == Received output is not as expected."
fi

Usually this logic works fine in checking the kernel version.
But recently i came across a server where the kernel version is little different

uname -r
2.6.32-279.39.1.el6.x86_64

If you look at the output, its has an extra numbers i.e., 39.1.

Can some one help me how to check for such extra characters, because with the current logic it fails to compare when we have extra digits in any one of the values.

Also it would be great if someone can give me a kernel version naming standard for Red Hat Linux.

Regards,
Veer

Can't help with the Red Hat Kernel version naming standard but this might help with this particular issue:

expected=2.6.32-279.el6.x86_64
received=$(uname -r)

exp_ver=${expected//\.el6.*/}
re_ver=${received//\.el6.*/}

if [ ${#re_ver} -lt ${#received} -a "$re_ver" '>' "$ex_ver" ]
then
    echo "Installed Version is higher than Expected."
    echo "Passed."
else
    echo "== FAILED == Received output is not as expected."
fi
1 Like

Thanks for your reply Chubler, I have couple of questions related to your code.

exp_ver=${expected//\.el6.*/}
re_ver=${received//\.el6.*/}

I was not aware of cutting out the string this way, i used to use awk or sed, but this looks more simpler,can you please explain me the syntax?

if [ ${#re_ver} -lt ${#received} -a "$re_ver" '>' "$ex_ver" ]

In this if statement, you are using '>' symbol for comaparision, why is the comparasion operator in quotes?

Regards,
Veer

Shell pattern substitution

This is the shell pattern substitution (man bash or man ksh should provide details for you). This is much more efficient that using sed or awk as it's internal to the shell and doesn't require loading an external executable before processing.

The substitution I supplied in my solution is a little misleading and could do with some improvement; although it does work for the supplied data.

  1. The backslash in \. is unnecessary, the dot character does not need to be escaped - it will only match with it's self, question mark ? is used to represent any single character
  2. // is used to replace all occurrences within the string not just the first.
  3. .* matches the literal dot followed by zero or more characters. In the example dot does follow el6, but those used to other regular expressions may interpret this as zero or more occurrences of any single character, not dot followed by zero or more characters.

I think a better pattern substitution would be echo ${expected/.el6*/}

String comparisons

Greater than and less than need to be escaped within [ ] context otherwise they are treated as redirection this is not the case with [[ and ]]. It's a matter of choice on using backslash or single quotes. the following are equivalent:

[ "$a" \< "$b" ]
[ "$a" '<' "$b" ]
[[ "$a" < "$b" ]]

I think i figured out the code to compare kernel & rpm version's on Redhat Linux.
Below is the code that i have written and tested for various RPM's & kernel version.

expected_ver=2.6.32-279.el6.x86_64
received_ver=2.6.32-279.39.1.el6.x86_64

expected_v=$(echo $expected_ver|awk -F'.' '{if($NF ~ /[xi]*86/ && $(NF-1) ~ /el/) NF=NF-2; else if ($NF ~ /[xi]*86/ && $(NF-1) !~ /el/) NF=NF-1; else if ($NF ~ /el/) NF=NF-1; for (i=1;i<=NF;i++) printf $i".";}'|sed 's/.$//')

received_v=$(echo $received_ver|awk -F'.' '{if($NF ~ /[xi]*86/ && $(NF-1) ~ /el/) NF=NF-2; else if ($NF ~ /[xi]*86/ && $(NF-1) !~ /el/) NF=NF-1; else if ($NF ~ /el/) NF=NF-1; for (i=1;i<=NF;i++) printf $i".";}'|sed 's/.$//')

if [ "$expected_v" = "$received_v" ]; then
	echo "Installed Version is same than Expected."
    echo "Passed."
else
	min=$(echo -e $expected_v"\n"$received_v|sort -V|head -n 1)
	if [ "$min" = "$expected" ];then
       echo "Installed Version is higher than Expected."
       echo "Passed."
	else
       echo "== FAILED == Received output is not as expected."
	fi
fi

I'm only interested in the first 3 'number groups' but this could be expanded as needed:

	declare -a TEMP2
	TEMP1=$(uname --kernel-release)
	TEMP2=(${TEMP1//[.-]/ })
	VERSION=$(((${TEMP2[0]} * 10000)\
		+ (${TEMP2[1]} * 100)\
		+ ${TEMP2[2]}))