Tuesday, November 16, 2021

[SOLVED] How to generate a list of available updates from yum and export to CSV, including current and updated version of each package?

Issue

I am running the following script on a Centos 7 box. The idea is to list packages that are currently available to update, along with the current version and new version. Once I get this accomplished, I will then send the results to a .csv file to import into excel.

Here is the bash script I am using:

#! /usr/bin/bash

echo \"timestamp\",\"package name\",\"current version\",\"update version\"
yum -q check-update| while read i
do
    i=$(echo $i) #this strips off yum's irritating use of whitespace
    if [ "${i}x" != "x" ]
    then
        TIMESTAMP=$( date +%D" "%r )
        UVERSION=${i#*\ }
        UVERSION=${UVERSION%\ *}
        PNAME=${i%%\ *}
        PNAME=${PNAME%.*}
        echo \"$TIMESTAMP\",$(rpm -q "${PNAME}" --qf '"%{NAME}","%{VERSION}","')${UVERSION}\"
    fi
done

This is what the results look like:

"timestamp","package name","current version","update version"
"06/20/18 02:19:37 PM","cloudbackup-updater","1.5.3","1.5.16-1"
"06/20/18 02:19:37 PM","dhclient","4.1.1","12:4.1.1-53.P1.el6.centos.4"
"06/20/18 02:19:37 PM","dhcp-common","4.1.1","12:4.1.1-53.P1.el6.centos.4"
"06/20/18 02:19:37 PM","kernel","2.6.32",""kernel","2.6.32",""kernel","2.6.32",""kernel","2.6.32",""kernel","2.6.32","2.6.32-696.30.1.el6"
"06/20/18 02:19:37 PM","kernel-firmware","2.6.32","2.6.32-696.30.1.el6"
"06/20/18 02:19:37 PM","kernel-headers","2.6.32","2.6.32-696.30.1.el6"

Notice the 5th line is repeating information. I think this is because the script is querying for the package "kernel" instead of the full name "kernel.x86_64" when it does the RPM query.

If I run

yum check-update

The following packages are available to update:

cloudbackup-updater.noarch
dhclient.x86_64
dhcp-common.x86_64
kernel.x86_64
kernel-firmware.noarch
kernel-headers.x86_64

What is wrong with my script, causing it to match only the first part of the name for each package instead of the full name?


Solution

The issue is the PNAME assignment

PNAME=${PNAME%.*}

This is something I have used to remove extensions from filenames. You are removing everything (and including) to the right of the period. Really no need for this line as far as I can see. Would also be a good idea to quote variable assignments. So something like this:

TIMESTAMP="$( date +%D" "%r )"
UVERSION="${i#*\ }"
UVERSION="${UVERSION%\ *}"
PNAME="${i%%\ *}"
#PNAME="${PNAME%.*}"

Output of $PNAME on these assignments:

cloudbackup-updater.noarch
dhclient.x86_64
dhcp-common.x86_64
kernel.x86_64
kernel-firmware.noarch
kernel-headers.x86_64

EDIT I am thinking that your while loop is parsing the output of yum incorrectly. Try changing that line to this:

yum -q check-update | tr -s " " | while read PNAME UVERSION extra

This should handle yum's space issue so you can remove i=$(echo $i). Also, this will read the individual values directly into the variables. Then, since $i no longer exists, you can change if [ "${i}x" != "x" ] to if [ "${PNAME}x" != "x" ] (This is actually a pretty clever way to check for a blank). So the final script should look like this:

echo \"timestamp\",\"package name\",\"current version\",\"update version\"
yum -q check-update | tr -s " " | while read PNAME UVERSION extra
do
    if [ "${PNAME}x" != "x" ]; then
        TIMESTAMP=$( date +%D" "%r )
        echo \"$TIMESTAMP\",$(rpm -q "${PNAME}" --qf '"%{NAME}","%{VERSION}","')${UVERSION}\"
    fi
done


Answered By - Jason