ObjectiveOur goal is to get used to the tools available to find out information about package dependencies on an RPM based system.
Operating System and Software Versions
- Operating system: Red Hat Enterprise Linux 7.5
- Software: rpm 4.11, yum 3.4.3
RequirementsPrivileged access to the system.
- # - requires given linux commands to be executed with root privileges either directly as a root user or by use of
- $ - given linux commands to be executed as a regular non-privileged user
IntroductionRPM, which stands for Red Hat Package Manager, is a well-known and mature package manager used by all Red Hat flavor distributions, as well as SuSE. With RPM the packager can define relations between packages, and even with versions of packages - for example, an Apache Tomcat server needs proper Java environment present to be able to run.
On the other hand, to install a Java environment, you don't need a Tomcat server - you may decide to run some different Java based application, maybe one written by yourself started by hand when needed to do it's job. In other words, the Tomcat server depends on Java.
RPM can make a sysadmin's life a lot easier by presenting these dependencies - and tools relying on RPM such as the
yumcan automatically solve these dependencies, and install all additional packages needed for a new component to run properly.
Gathering informationTo find out the list of packages that foo.bar package depends on, simply run:
# yum deplist foo.barAnd to find the list of packages that require (depend on) package foo.bar:
rpm -q --whatrequires foo.barA real life example with a generic package:
bash. Let's see what packages needed by the bash package:
# yum deplist bash package: bash.x86_64 4.2.46-30.el7 dependency: libc.so.6()(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.11)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.14)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.15)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.2.5)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.3)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.3.4)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.4)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libc.so.6(GLIBC_2.8)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libdl.so.2()(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libdl.so.2(GLIBC_2.2.5)(64bit) provider: glibc.x86_64 2.17-222.el7 dependency: libtinfo.so.5()(64bit) provider: ncurses-libs.x86_64 5.9-14.20130511.el7_4 dependency: rtld(GNU_HASH) provider: glibc.x86_64 2.17-222.el7 provider: glibc.i686 2.17-222.el7
From the package perspective,
bashis a very generic one, and as seen above, depends on a few core package. But if we'd like to install something much more dependent, say, the
konzoleKDE terminal emulator on a Red Hat Linux with a Gnome desktop manager, we may get more than one page long dependency list. And with
konzole, the case is even more complicated, as it relies on QT and KDE packages, so in order to install it, you will need to install the whole KDE environment beside Gnome (what you can certainly do) to provide everything
To get a more insight of what packages will be installed, check the list provided by yum before starting the installation:
# yum install konsole Resolving Dependencies --> Running transaction check ---> Package konsole.x86_64 0:4.10.5-4.el7 will be installed --> Processing Dependency: konsole-part = [...]
And in the summary we can see that the installation will use a lot more space on disk in the end, then the size of the package we need:
[...] --> Running transaction check ---> Package boost-system.x86_64 0:1.53.0-27.el7 will be installed ---> Package boost-thread.x86_64 0:1.53.0-27.el7 will be installed --> Finished Dependency Resolution Dependencies Resolved ============================================================================================================================== Package Arch Version Repository Size ============================================================================================================================== Installing: konsole x86_64 4.10.5-4.el7 rhel-7-server-rpms 78 k Installing for dependencies: OpenEXR-libs [...]
This is a lot, but we got a useful information on how much space will be used. This is especially useful if we install many packages in one transaction.
[...] Transaction Summary ============================================================================================================================== Install 1 Package (+120 Dependent packages) Total download size: 108 M Installed size: 307 M
While in this case the transaction is wasteful, the goal of dependencies is ultimately about saving resources: if someone implements some functionality in his/her code, and that can be called on the system, the next developer may not need to implement the same functionality again, but use the already existing implementation. For the
konzoleexample, if you want to install
akregatornext time, the system will have many dependencies solved already, as
akregatoralso relies on
kdelibs, and such.
We can use
rpmutility the get the information the other way around: let's list the installed packages that require the
# rpm -q --whatrequires bash dracut-033-535.el7.x86_64 initscripts-9.49.41-1.el7.x86_64 autofs-5.0.7-83.el7.x86_64 lvm2-2.02.177-4.el7.x86_64 rsyslog-8.24.0-16.el7.x86_64
Cleaning unneeded packagesIf we keep our systems up to date, and change or extend their roles, "junk" packages will inevitably appear. In the package sense junk means no longer needed and/or deprecated packages. To follow the above example, we no longer need
akregator, because we moved the "service" of RSS handling to a hypothetical central RSS concentrator within our system, so after migrating our feeds to the central place, we uninstall the local RSS handling application. That will not remove all the KDE packages, as many other packages may depend on them. But if not, those packages are junk, and will consume resources, including longer update times, as
yumby default will update everything blindly it finds new packages/errata for.
Spending resources on upgrading a few unneeded packages on a laptop with broadband connection and SSD may not seem to be an issue, but imagine a datacenter with hundreds or thousands of computers, and you get the picture. It is generally a good idea to keep all systems simple, and resource management is only one point. The more complex a system, the more error prone it is. More components mean more possible bugs.
To get an overview on unneeded packages installed on the system, we can use yum and package-cleanup the same way as on CentOS, or another feature of yum,
When using any of these tools it is advised to double-check what
yumis going to remove, and possibly test what the cleaning will result in on testing machines with identical package content before cleaning up the production systems.
These tools are indeed clever, but not all-knowing: for example, there will be no entry in the rpm database about a custom PHP application running on top of a webserver that calls
cupsto print out incoming orders on a printer connected to the server. That is, there can be an entry if the application is packaged with the right dependencies included, and installed properly with
yum- but that takes effort, and all services need to be packaged the same way if you want to feel safe with yum-based automatic cleanups.
Solving dependency problemsEspecially in large environments, there can be dependency issues while installing or upgrading systems.
The below screenshot shows a simple issue:
In the above terminal screen we try to install the
nrpepackage, the client needed to monitor many aspects of the system with Nagios. We downloaded the client for the distribution, but both
yumfails with the same error: the
nrpepackage requires (depends on) the
nagios-commonpackage. In this example we can obtain the needed package from the same source, and when installing both of them the
rpmutility sees that the dependency we failed on earlier will be satisfied by the end of the transaction and installs both packages, exiting silently with success.