B.M.A.G.Piette@durham.ac.uk
On a Linux system, the installed RPMS come from various sources: the distribution packages, the extra packages (powertools) installed afterwards as well as the RPM patches. When managing a network of Linux systems, one question that arises is if all the expected RPMS are installed and up to date. This is particularly important to check that all the latest patches have been installed.
Sysfrpm
is a tool which checks and compare lists of RPMS.
In particular it can compare the list of installed packages with lists
of packages written in files or the rpm files in a directory or any
combination of both.
When maintaining a large number of computers, it is common to install the same packages on all of them. This include in particular all the patches. If a computer is unavailable for a short time when new packages are installed across the network, it is easy to forget about it and forget to update that computer when it is brought back. When installing a new computer it is also important to install the common set of packages. One must thus compare the list of installed packages with the list of expected packages.
When upgrading the operating system on a computer, one wants to install the same packages as before, but, when they are available, with a more recent version. One thus need a way to compare two lists of packages regardless of their version.
.sysfrpm
was designed to check if the packages installed on a given
computer match a given list of packages. This list of packages can be
extracted from the rpm files in various directories or from files that
contain lists of packages or any combinations of both.
If one keeps all the rpm files that are installed in a few directories,
say one for the powertools and one for the patch rpms, sysfrpm
can check these directories and find out which package has not been installed
yet. One can also specify hosts specific files to add or remove some packages
from the expected list.
Sysfrpm
checks the RPMS in 3 stages:
SRC_LIST
) of all expected RPMS.INST_LIST
)of all installed RPMS.SRC_LIST
but not in INST_LIST
), the extra
packages (packages in INST_LIST
but not in SRC_LIST
) and
then the packages which are not up to date (packages present in both in
INST_LIST
and SRC_LIST
but with different versions).
Sysfrpm
can also produce lists of packages build from multiple
sources or from the installed packages.
Here are a few examples:
sysfrpm -mf MASTER_FILE -D
sysfrpm -i
sysfrpm -d DIR_NAME -CS
sysfrpm -n LIST_1 -in LIST_2 -D -NoWrongVer
The syntax for sysfrpm
is as follow
sysfrpm SRC_LIST [INST_LIST] [COMMAND] [FLAGS]
SRC_LIST
-name=n NAME
: a file containing a list of RPMS.-dir=d NAME
: a directory containing rpm
files.-MasterFile=mf NAME
: a master file: a list of files and
directories to scan.-installed=i
: the list of installed directories.INST_LIST
-InstName=in NAME
: a list of RPMS in a file.-InstDir=id NAME
: a directory containing rpm
files.-InstMasterFile=imf NAME
: a master file: a list of files
(RPMS list) and directories to scan.COMMAND
SRC_LIST
as an
rpm list ordered in
alphabetical order. The output has the same format as the command
rpm -q -a --queryformat "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n"
.-help
: display a help message.-diff=D
: compare the SRC_LIST
with the
INST_LIST
and list the missing RPMS, the extra RPMS and the
RPMS with a version mismatch. The exit status value for
sysfrpm
is 0
if SRC_LIST
and INST_LIST
are identical (no
output) and 1
if there are differences.
-check=C
: does the same as diff
but without any
output. The only side effect is the exit code : 0
if SRC_LIST
and INST_LIST
are identical and
1
if there are differences.
-CheckSrc=SC
: Check that all the packages in
SRC_LIST
are properly installed. Lists the missing RPMS,
and the RPMS with a version mismatch. The exit status value for
sysfrpm
is 0
if SRC_LIST
and
INST_LIST
are identical (no output) and 1
if there are differences.
-DiffList=DL
: print as an ordered list the difference
between SRC_LIST
and INST_LIST
.FLAGS
NoMissing=nm
: do not display the missing packages
(diff=D
and CheckSrc=SC
commands). NoExtra=ne
: do not display the extra packages
(diff=D
command). NoWrongVer=nw
: do not display the packages for which
there is a version mismatch
(diff=D
and CheckSrc=SC
commands).
The master file is a list of files (one per line) and directories from
which a list of RPMS is constructed. Empty lines and lines starting with a
#
are ignored, allowing to put comments in the master file.
Directories are scanned for any ".rpm"
file.
The -MasterFile=mf
argument builds the SRC_LIST
while the -InstMasterFile=imf
argument builds the INST_LIST
.
Each RPM is added to the RPM list and the RPM name is used as the key. Except when requested (see below), the key is kept unique, meaning that any existing RPM version and architecture are overwritten by any new ones for the same package. This means that the RPM lists in the master file must be ordered so that RPM update or patches come after the original list.
One can also remove RPMS from the RPM list either by removing en entire list or one rpm at a time.
A master file is used to specify what the expected list of installed RPMS should be. The master file will normally be the same for every host on the network. The specificities, if they exist, of individual hosts are taken into account using host specific files.
Each line in the master file is taken as a path. Empty lines or lines
staring with a #
are ignored. The path can point to a file or a
directory. Files or directories that do not exist are ignored.
If a path contains the string $h
or $H
, it is replaced
by the host name in lower case and upper case letter respectively.
This allows the use of host specific lists.
Entries can be of the following type:
FILE_NAME
: the rpm listed in the file are added to the list
(see the RPM file syntax below). By default the version and
architecture of an RPM already in the list is overwritten any new one.DIR_NAME
: the ".rpm"
files in that directory are
added to the list (non ".rpm"
files are ignored).
By default the version and architecture of an RPM already in the list
is overwritten any new one.@PATH_NAME
: the RPMS listed in the file or the
directory are added to the list and the key (rpm name) is not kept
unique: any
entry is added to the list even when the key already exists in the
list and even if the existing key has the same version and
architecture. -PATH_NAME
: the RPMS listed in the file or the
directory are removed from the list. The version and architecture are
not taken into account, so any RPM listed is removed from the list
regardless of its value. Non existing RPMS are ignored.-@PATH_NAME
: the RPMS listed in the file or the
directory are removed from the list but only if it matches the version
and the architecture value.
Each line in the file is taken as an RPM name of the form
NAME-VERSION-RELEASE.ARCH
. Empty lines or lines staring with a
#
are ignored. Entries can be of the following type:
RPM_NAME
: by default, add the name to the list and, if the
package is already in the list, overwrite the existing value for the
RPM. The master file might dictate that the RPM entry must not be
overwritten or that the RPM must be removed from the list. -RPM_NAME
: remove the RPM from the list
regardless of its version and the architecture values.+RPM_NAME
: add the RPM to the list
and overwrite any exiting value for that package.
This can be used to overwrite a subtraction ordered from the master
file.-@RPM_NAME
: remove the RPM from the list
but only if the version and the architecture values matches the entry.+@RPM_NAME
: add the RPM to the list
without overwriting exiting entries.
The master file will typically list the following lists of packages (the path names are the ones we assumes for our examples below):
/redhat7.1_disk1/RedHat/RPMS
)./usr/local/System/RedHat7.1/ContribRPM_STDINST
) on all or
most systems./usr/local/System/RedHat7.1/Patches
and /usr/local/System/RedHat7.1/Patches/Kernel
).
The list of distribution packages will be put into a file
(/usr/local/System/RedHat7.1/redhat7.1.DIST
) the reason being that
they are not all installed.
The Master File (redhat7.1.mf
) will then look as follow:
/usr/local/System/RedHat7.1/redhat7.1.DIST /usr/local/System/RedHat7.1/ContribRPM_STDINST /usr/local/System/RedHat7.1/Patches /usr/local/System/RedHat7.1/Patches/Kernel /usr/local/System/RedHat7.1/rpm_list.$h
We now create the file (redhat7.1.DIST
) that will contain all
the installed distribution packages by reading the packages from
the distribution directory (/redhat7.1_disk1/RedHat/RPMS
).:
# sysfrpm -d @/redhat7.1_disk1/RedHat/RPMS > redhat7.1.DIST
One must then remove from the distribution list the packages that are
not installed. First we create the list (redhat7.1.DIST.miss
)
of RPMS that are not installed:
# sysfrpm -CS -n redhat7.1.DIST -nw > redhat7.1.DIST.missWe then create the master file
redhat7.1.DIST.mf
@redhat7.1.DIST -@redhat7.1.DIST.missto subtract the packages in
redhat7.1.DIST.miss
from
redhat7.1.DIST
:
# sysfrpm -mf redhat7.1.DIST.mf > redhat7.1.DIST2 # mv redhat7.1.DIST2 redhat7.1.DISTOne then does a further check:
# sysfrpm -mf redhat7.1.m -Dand all packages listed as having the wrong version can be added to the
redhat7.1.DIST
file, and all packages listed as extras can be added
to the redhat7.1.DIST
file with the @
prefix.
If a host has extra packages or packages that have not been installed,
one can list those in the host specific file rpm_list.HOST_NAME
where HOST_NAME
is the name of the host. It will contain the
following type of entries:
@
prefix.-
or
-@
. The former remove the package regardless of the version, while
the later only removes the package if there is a version match.
Let us now consider a concrete example. Most computers are assumed to have the
same packages installed except gates
which because of disk limitation
only has a subset of packages installed, and trovald
which has a few
extra packages.
The rpm files installed as in the following directories:
/packages/redhat7.2_disk1/RedHat/RPMS
: the distribution RPMS./packages/RPMS/extras
: powertools or extra RPM files that
we have installed./packages/RPMS/patches
: all the latest patches installed./packages/RPMS/patches/kernel
: the latest kernel patches./packages/RPMS/patches/kernel_old
: some old kernel patches.We will save the rpm lists and master files in the directory
/usr/local/sys/rpm_check
(which can be changed to anything one likes
but should be on a partition NFS mounted on every host).
First we create the list of distribution RPMS with the command
# cd /usr/local/sys/rpm_check # sysfrpm -d @/packages/redhat7.2_disk1/RedHat/RPMS > redhat7.2.DISTThis list of packages should not change, so we can create a list file for it.
Then we create the master file rpm_lists.mf
:
/usr/local/sys/rpm_check/redhat7.2.DIST /packages/RPMS/extras /packages/RPMS/patches /packages/RPMS/patches/kernel @/usr/local/sys/rpm_check/rpm_list.multi_key @/usr/local/sys/rpm_check/rpm_list.multi_key.$h -/usr/local/sys/rpm_check/rpm_rem_list -@/usr/local/sys/rpm_check/rpm_rem_list.$h /usr/local/sys/rpm_check/rpm_list.$h
The first line lists all the distribution RPMS. The next three line are the directories where all the extra rpms have been saved.
In the line /usr/local/sys/rpm_check/rpm_list.$h
, the $h
will be replace by the host name. In our example, we will have a file
called rpm_list.trovald
which lists the extra packages installed on
trovald. If the file does not exist for a given hosts, it is simply ignored.
The files rpm_list.multi_key
and rpm_list.multi_key.$h
will contain
the list of packages that are installed for different versions (for all
computers and for specific hosts respectively). This is typically the case
for kernel patches. Initially these file will be created with no content.
Then after running sysfrpm
the first time, one will discover which
packages need to be added to these lists.
The file rpm_rem_list
will contain the list of packages that must be
removed from the list build so far. When upgrading packages, some old rpms
are sometimes removed without
being replaced. Rather that editing the other rpm list files it is neater to
remove them here.
The file rpm_rem_list.$h
will contains the list of packages that must
be removed for specific hosts. In our example we will expect to have one for
gates
.
After creating these configuration files, one runs the command
# sysfrpm -mf /usr/local/sys/rpm_check/rpm_lists.mf -diffto check the configuration on the current host. The output will display three types of packages:
EXTRA RPMS
,
MISSING RPMS
and WRONG VERSION RPMS
. Each must be looked at
separately:
MISSING RPMS
: the packages from that list that were not
installed on this hosts because they were forgotten should be installed now.
The other packages names should be added to the file rpm_rem_list
or rpm_rem_list.$h
. One can also subtract them in the rpm_list.$h
by using the prefix -
(minus sign) for the package name.EXTRA RPMS
: one must find out if these packages have just been
installed on this host or on most of them and why it is not listed in the
several directories or rpm lists. Packages that are installed on one or
possibly a few hosts, are likely to be added to the appropriate file
rpm_list.$h
or rpm_list
.
Otherwise one will have to find the package files and
probably copy them into the directory /packages/RPMS/extras
.WRONG VERSION RPMS
: these packages can be rpms that one forgot to
patch (upgrade). These should be upgraded now. If not, the package names
should be added to the file rpm_list
or rpm_list.$h
.
The other possibility is that
these packages are installed more than once. If so, they can be added to the
lists rrpm_list.multi_key
and rpm_list.multi_key.h
. One can also
add and remove multiple version packages in the rpm_list.$h
using the
@
prefix. Setting up multiple version packages properly is by far the
trickiest part of configuring sysfrpm
. If for example, sysfrpm
produces the following output on the hosts
trovald:
# MISSING RPM : openssh-askpass-2.9p2-11.7 openssh-2.9p2-11.7 openssh-server-2.9p2-11.7 openssh-clients-2.9p2-11.7 openssh-askpass-gnome-2.9p2-11.7 # EXTRA RPM : kernel-2.4.3-12.i386 mtools-3.9.7-4 # WRONG VERSION RPM : apache-1.3.22-1.7.1.i386 apache-devel-1.3.22-1.7.1.i386 apache-manual-1.3.22-1.7.1.i386 mod_ssl-2.8.5-0.7.i386we can solve the inconsistency by creating the file
/usr/local/sys/rpm_check/rpm_list.trovald
(we do it in a single file for
simplicity):
# MISSING RPM : -openssh-askpass-2.9p2-11.7 -openssh-2.9p2-11.7 -openssh-server-2.9p2-11.7 -openssh-clients-2.9p2-11.7 -openssh-askpass-gnome-2.9p2-11.7 # EXTRA RPM : +@kernel-2.4.3-12.i386 mtools-3.9.7-4 # WRONG VERSION RPM : apache-1.3.22-1.7.1.i386 apache-devel-1.3.22-1.7.1.i386 apache-manual-1.3.22-1.7.1.i386 mod_ssl-2.8.5-0.7.i386Notice that for the
kernel-2.4.3-12.i386
package we use the
@
prefix to add this entry without overwriting any existing one for
the package kernel
.
One usually has to experiment with this as kernel
packages are often
installed more than once.
After doing this on every host, one can then run sysfrpm
on every
hosts at regular interval using a cron job. Here is a csh
script file
that does the job, using sysf
to get the list of all hosts,
and Emailinmg the result to the user admin
:
#!/bin/csh set SYSFRPM_PATH="/usr/local/sys/rpm_check" echo "" >>! /tmp/ck.log foreach h (`sysf -lah -h ALL`) echo $h >> /tmp/ck.log (rsh $h sysfrpm -mf $SYSFRPM_PATH/rpm_lists.mf -diff) >> & /tmp/ck.log end mail -s "sysfrpm_check" admin < /tmp/ck.log