Using RPM to find package dependencies

I recently discovered that is it actually rather difficult to determine which packages depend on a particular package using the RedHat Package Manager, and I ended up writing a short script to list all the dependencies for a particular package.

Initially I tried to use  rpm  to discover what packages depended  lz4 .

The first thing I did was check the package names.

# rpm -q -a lz4
lz4-1.7.5-2.el7.i686
lz4-1.7.5-2.el7.x86_64
#

Then I checked to see what packages depended on these packages (or at least I thought I was checking for packages that depended on them).

rpm -q --whatrequires lz4-1.7.5-2.el7.i686 lz4-1.7.5-2.el7.x86_64
no package requires lz4-1.7.5-2.el7.i686
no package requires lz4-1.7.5-2.el7.x86_64

Great – Nothing depends on them! But, when I try to delete these packages I get an error…

# rpm --erase --allmatches lz4
error: Failed dependencies:
        liblz4.so.1()(64bit) is needed by (installed) systemd-libs-219-57.el7.x86_64
        liblz4.so.1()(64bit) is needed by (installed) systemd-219-57.el7.x86_64
        liblz4.so.1 is needed by (installed) systemd-libs-219-57.el7.i686

What is going on?

It turns out that in RedHat each package provides one or more capabilities and can also depend on one or more capabilities provided by several different packages (NOT the packages themselves).

So to discover what packages depend on a particular package, you need to find out what capabilities that package provides and then check each one of those capabilities to see which packages depend on them.

rpm -q --provides lz4
liblz4.so.1()(64bit)
lz4 = 1.7.5-2.el7
lz4(x86-64) = 1.7.5-2.el7
liblz4.so.1
lz4 = 1.7.5-2.el7
lz4(x86-32) = 1.7.5-2.el7

rpm -q --whatrequires "liblz4.so.1()(64bit)" \
"lz4 = 1.7.5-2.el7" "lz4(x86-64) = 1.7.5-2.el7" "liblz4.so.1" \
"lz4(x86-32) = 1.7.5-2.el7"
systemd-libs-219-57.el7.x86_64
systemd-219-57.el7.x86_64
no package requires lz4 = 1.7.5-2.el7
no package requires lz4(x86-64) = 1.7.5-2.el7
systemd-libs-219-57.el7.i686
no package requires lz4(x86-32) = 1.7.5-2.el7

Yes – you really do need to include each capability in quotes!

Since I really don’t want to do that any more often than I have to I wrote a script to do it for me.

#!/bin/bash
#
# redhat-get-dependencies.sh
#
# Lists all the installed packages that are dependent on one of the packages
# specified.
#
# This  program  is free software: you can redistribute it and/or modify  it
# under the terms of the GNU General Public License as published by the Free
# Software  Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This  program  is  distributed  in the hope that it will  be  useful,  but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public  License
# for more details.
#
# You  should  have received a copy of the GNU General Public License  along
# with this program. If not, see <http://www.gnu.org/licenses/>
#
#  19 Sep 18   0.1   - Initial version - MEJT
#              0.2   - Now only evaluates the dependencies once and displays
#                      the number of dependent packages against each package
#                      name - MEJT
#                    - Added options to display the version number and force
#                      package names and the number of dependent packages to
#                      be shown ('--version' and '--verbose') - MEJT
#                    - Dependencies  not shown indented if the package names
#                      are shown - MEJT
#
_version="0.2"
_count=0
_flag=false
 
# Scan command line arguments
while test $# -gt 0do
  case "$1" in
  --verbose|-v)
    _flag=true;;
  --version)
    echo "$0: version $_version"
    exit 0 ;;
  --help)
    echo "syntax: $0 PACKAGE [PACKAGE...]"
    echo "  -v, --verbose           show package names and number of"
    echo "                          dependent packages"
    echo "      --help              display this help and exit"
    echo "      --version           output version information and exit"
    exit 0 ;;
  -*) # Unrecognized qualifier!
    echo "$0: unrecognized option '$1'"
    echo "Try '$0 --help' for more information."
    exit 0 ;;
  *) # Append each argument to args[] (preserving quoted strings).
    _args[$_count]=$1
    _count=$((_count+1)) ;;
  esac
  shift
done
 
# Get depandant packages for each package based on capability.
if [ "$_count" -gt 0 ]; then
  for _package in "${_args[@]}"do
    # Start by counting the number of dependancies.
    _dependancies=$(rpm -q "$_package" --provides | while read _x; \
      do rpm -q --whatrequires "$_x"done \
      | grep -v "no package" | grep -v "not installed" |sort -u)
    # If there are no dependencies check the next package.
    if [ "$(echo -n "$_dependancies" | wc -l)" -gt 0 ]; then
      if [ "$_count" -gt 1 ] || [ $_flag = true ]; then 
        echo "$_package : $(echo "$_dependancies" | wc -l)"
        echo "$_dependancies" | sed "s/^/  /"
      else # Don't indent dependencies unless displaying package name/count.
        echo "$_dependancies"
      fi
    fi
  done
else
  echo "$0: no package specified."
  echo "Try '$0 --help' for more information."
  exit -1
fi
 
# Exit!
exit $?

Now I can easily check the dependencies for multiple packages.

./sh-redhat-get-dependancies.sh lz4 zlib
lz4 : 3
  systemd-219-57.el7.x86_64
  systemd-libs-219-57.el7.i686
  systemd-libs-219-57.el7.x86_64
zlib : 75
  bind-libs-9.9.4-51.el7.x86_64
  bind-libs-lite-9.9.4-51.el7.x86_64
  bind-utils-9.9.4-51.el7.x86_64
  binutils-2.27-28.base.el7_5.1.x86_64
  biosdevname-0.7.3-1.el7.x86_64
  btrfs-progs-4.9.1-1.el7.x86_64
  cairo-1.14.8-2.el7.x86_64
  cairomm-1.12.0-1.el7.x86_64
  compat-libtiff3-3.9.4-11.el7.x86_64
  cpp-4.8.5-28.el7_5.1.x86_64
  cracklib-2.9.0-11.el7.i686
  cracklib-2.9.0-11.el7.x86_64
  cups-libs-1.6.3-35.el7.x86_64
  curl-7.29.0-46.el7.x86_64
  deltarpm-3.6-3.el7.x86_64
  elfutils-libelf-0.170-4.el7.i686
  elfutils-libelf-0.170-4.el7.x86_64
  elfutils-libs-0.170-4.el7.i686
  elfutils-libs-0.170-4.el7.x86_64
  file-5.11-33.el7.x86_64
  file-libs-5.11-33.el7.x86_64
  gcc-4.8.5-28.el7_5.1.x86_64
  gcc-c++-4.8.5-28.el7_5.1.x86_64
  gcc-gfortran-4.8.5-28.el7_5.1.x86_64
  gdb-7.6.1-110.el7.x86_64
  genisoimage-1.1.11-23.el7.x86_64
  GeoIP-1.5.0-11.el7.x86_64
  git-1.8.3.1-14.el7_5.x86_64
  glib2-2.54.2-2.el7.x86_64
  gnupg2-2.0.22-4.el7.x86_64
  gnutls-3.3.26-9.el7.x86_64
  info-5.1-5.el7.x86_64
  iprutils-2.4.15.1-1.el7.x86_64
  kexec-tools-2.0.14-17.2.el7_4.x86_64
  kmod-20-21.el7.x86_64
  kmod-libs-20-21.el7.x86_64
  libcurl-7.29.0-46.el7.x86_64
  libpng12-1.2.50-10.el7.x86_64
  libpng-1.5.13-7.el7_2.x86_64
  libssh2-1.4.3-10.el7_2.1.x86_64
  libtiff-4.0.3-27.el7_3.x86_64
  libxml2-2.9.1-6.el7_2.3.x86_64
  libxml2-python-2.9.1-6.el7_2.3.x86_64
  libxslt-1.1.28-5.el7.x86_64
  man-db-2.6.3-9.el7.x86_64
  mariadb-libs-5.5.56-2.el7.x86_64
  mesa-libEGL-17.2.3-8.20171019.el7.x86_64
  neon-0.30.0-3.el7.x86_64
  nss-tools-3.36.0-5.el7_5.x86_64
  openssh-7.4p1-16.el7.x86_64
  openssh-clients-7.4p1-16.el7.x86_64
  openssh-server-7.4p1-16.el7.x86_64
  openssl098e-0.9.8e-29.el7_2.3.x86_64
  openssl-1.0.2k-12.el7.x86_64
  openssl-libs-1.0.2k-12.el7.x86_64
  open-vm-tools-10.1.10-3.el7_5.1.x86_64
  python-deltarpm-3.6-3.el7.x86_64
  python-dmidecode-3.12.2-2.el7.x86_64
  python-libs-2.7.5-69.el7_5.x86_64
  python-lxml-3.2.1-4.el7.x86_64
  rpm-4.11.3-32.el7.x86_64
  rpm-build-4.11.3-32.el7.x86_64
  rpm-build-libs-4.11.3-32.el7.x86_64
  rpm-libs-4.11.3-32.el7.x86_64
  rpm-python-4.11.3-32.el7.x86_64
  rpm-sign-4.11.3-32.el7.x86_64
  rsyslog-8.24.0-16.el7_5.4.x86_64
  subversion-1.7.14-14.el7.x86_64
  subversion-libs-1.7.14-14.el7.x86_64
  sudo-1.8.19p2-14.el7_5.x86_64
  systemd-219-57.el7.x86_64
  util-linux-2.23.2-52.el7.x86_64
  wget-1.14-15.el7_4.1.x86_64
  xmlsec1-1.2.20-7.el7_4.x86_64
  xmlsec1-openssl-1.2.20-7.el7_4.x86_64

Advertisements
This entry was posted in CentOS, RedHat and tagged , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.