Learning RPM
Overview
RPM (RPM Package Manager) can install, update, erase, verify packages. It is default package manager for Red Hat
based distributions. RPM works on both installed and raw rpm packages. RPM doesn’t automatically resolve dependencies
of packages. Dependencies need to collect manually and install using rpm command.
Package Naming Convention
RPM packages are suffixed with rpm extension and follows a fixed naming convention. Every RPM package follows following format.
PACKAGE_NAME-PACKAGE_VERSION-RELEASE_VERSION-OS_NAME-ARCHITECTURE.rpm
Example:
tree-1.6.0-10.el7.x86_64.rpmHere tree is the name of the package. 1.6.0 is version of tree. 10 is package release version, means how many times this version of application is packaged. Same version of application may need to repackage for updating package metadata. Next field is indented operating system, el7 means Red Hat Enterprise Linux (EL) 7. Last field is architecture type which is x86_64.
Obtaining Packages
I am using CentOS 7 for running examples in this article. Although better alternate for downloading and resolving
dependencies is yum but for the sake of this article I will be downloading packages manually using curl.
$ cat /etc/centos-releas
CentOS Linux release 7.6.1810 (Core)Packages for this version of CentOS is located in following URL:
http://mirror.centos.org/centos/7.6.1810/os/x86_64/Packages/
Lets create a shell variable with this URL:
$ CENTOS7_PACKAGE_ROOT="http://mirror.centos.org/centos/7.6.1810/os/x86_64/Packages"I will search package names using browser and download using curl. I got from searching that complete package name of
tree command is tree-1.6.0-10.el7.x86_64.rpm. Now I can download tree like below:
$ curl -O $CENTOS7_PACKAGE_ROOT/tree-1.6.0-10.el7.x86_64.rpm
$ ls
tree-1.6.0-10.el7.x86_64.rpmInstall/Update Package
As rpm doesn’t automatically resolve dependencies, we have to manually resolve all dependencies. Let’s first install a
basic program without any dependencies.
tree-1.6.0-10.el7.x86_64.rpm package doesn’t have any dependency. We can install directly with following command:
$ sudo -i tree-1.6.0-10.el7.x86_64.rpmrpm doesn’t show any messages if installs successfully. We can add vh option to add verbose message with hash to
denote progress.
$ sudo -ivh tree-1.6.0-10.el7.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:tree-1.6.0-10.el7 ################################# [100%]For upgrading a package we have to use -U option. As we just install tree trying to upgrade this version again will
do nothing. But we can re-install this package with --reinstall option.
$ sudo -U tree-1.6.0-10.el7.x86_64.rpm
package tree-1.6.0-10.el7.x86_64 is already installed
$ sudo --reinstall -vh tree-1.6.0-10.el7.x86_64.rpm
Preparing... ################################# [100%]
Updating / installing...
1:tree-1.6.0-10.el7 ################################# [ 50%]
Cleaning up / removing...
2:tree-1.6.0-10.el7 ################################# [100%]If we want to upgrade a package only if its already installed we can use -F option.
$ sudo -F tree-1.6.0-10.el7.x86_64.rpmNow for installing packages with dependencies we have to collect and install dependencies manually. Let’s try install
nmap package which have dependencies. I have download the nmap packge file named nmap-6.40-16.el7.x86_64.rpm. Now if
we run the install command like below:
$ sudo -i nmap-6.40-16.el7.x86_64.rpm
error: Failed dependencies:
libpcap.so.1()(64bit) is needed by nmap-2:6.40-16.el7.x86_64
nmap-ncat = 2:6.40-16.el7 is needed by nmap-2:6.40-16.el7.x86_64We can see from the error message that nmap has two dependencies which is not currently installed in our machine. We
can see that libcap.so.1 is a library and nmap-ncat in another package.
Now if we search in $CENTOS7_PACKAGE_ROOT URL using a web browser we can easily find following packages
libpcap-1.5.3-11.el7.x86_64.rpm and nmap-ncat-6.40-16.el7.x86_64.rpm. Now lets try to first install dependencies.
$ sudo -i libpcap-1.5.3-11.el7.x86_64.rpm
$ sudo -i nmap-ncat-6.40-16.el7.x86_64.rpmNow we can install nmap without any error using following command:
$ sudo -i nmap-6.40-16.el7.x86_64.rpmRemove Package
We can remove a package using --erase or -e option like below:
$ sudo rpm -e nmapNote we have given only package name not the whole rpm file name. This will only remove nmap and won’t remove its
dependencies. Again dependencies have to be removed manually.
Install and erase both takes --test parameter. In this case rpm dry runs the command and doesn’t change anything.
$ rpm -evh --test nmapQuery Package
RPM has very flexible way to search and gather information about installed and raw rpm packages. Query command is
--query or -q for short. By default rpm queries on installed packages.
For querying all installed packages use -a with query command.
$ rpm -qa
selinux-policy-targeted-3.13.1-229.el7.noarch
grub2-common-2.02-0.76.el7.centos.noarch
kexec-tools-2.0.15-21.el7.x86_64
kbd-legacy-1.15.5-15.el7.noarch
openssh-clients-7.4p1-16.el7.x86_64
# ... (Showing first 5 lines)We can query detailed information about a package using -i option:
$ rpm -qi bash
Name : bash
Version : 4.2.46
Release : 31.el7
Architecture: x86_64
Install Date: Tue 28 May 2019 12:45:09 PM +06
Group : System Environment/Shells
Size : 3667773
License : GPLv3+
Signature : RSA/SHA256, Mon 12 Nov 2018 08:21:49 PM +06, Key ID 24c6a8a7f4a80eb5
Source RPM : bash-4.2.46-31.el7.src.rpm
Build Date : Tue 30 Oct 2018 11:09:33 PM +06
Build Host : x86-01.bsys.centos.org
Relocations : (not relocatable)
Packager : CentOS BuildSystem <http://bugs.centos.org>
Vendor : CentOS
URL : http://www.gnu.org/software/bash
Summary : The GNU Bourne Again shell
Description :
The GNU Bourne Again shell (Bash) is a shell or command language
interpreter that is compatible with the Bourne shell (sh). Bash
incorporates useful features from the Korn shell (ksh) and the C shell
(csh). Most sh scripts can be run by bash without modification.We can also filter packages using these fields. Like for listing all packages with GPLv3+ license we can write:
$ rpm -qa License=GPLv3+
sed-4.2.2-5.el7.x86_64
coreutils-8.22-23.el7.x86_64
readline-6.2-10.el7.x86_64
cpio-2.11-27.el7.x86_64
less-458-9.el7.x86_64
# ... (Showing first 5 lines)For listing all files of a package -l option is used:
$ rpm -ql bashFor listing only documentation -d option and for only configuration file -c option is used:
$ rpm -qd bash
/usr/share/doc/bash-4.2.46/COPYING
/usr/share/info/bash.info.gz
/usr/share/man/man1/..1.gz
/usr/share/man/man1/:.1.gz
/usr/share/man/man1/[.1.gz
# ... (Showing first 5 lines)
$ rpm -qc bash
/etc/skel/.bash_logout
/etc/skel/.bash_profile
/etc/skel/.bashrcDependencies of a package can be viewed using -R option.
$ rpm -qR bash
/bin/sh
config(bash) = 4.2.46-31.el7
libc.so.6()(64bit)
libc.so.6(GLIBC_2.11)(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.15)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
libc.so.6(GLIBC_2.8)(64bit)
libdl.so.2()(64bit)
libdl.so.2(GLIBC_2.2.5)(64bit)
libtinfo.so.5()(64bit)
rpmlib(BuiltinLuaScripts) <= 4.2.2-1
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rtld(GNU_HASH)
rpmlib(PayloadIsXz) <= 5.2-1We can also query which package a certain file belongs to using -f option:
$ rpm -qf /etc/yum.conf
yum-3.4.3-161.el7.centos.noarchWe can also filter package by group. We can run the following command to find out installed package’s groups.
$ rpm -qa --qf "%{GROUP}\n" | sort -u
Applications/Archiving
Applications/Databases
Applications/Editors
Applications/File
Applications/Internet
Applications/Multimedia
Applications/Publishing
Applications/System
Applications/Text
Development/Languages
Development/Libraries
Development/System
Development/Tools
Public Keys
System Environment/Base
System Environment/Daemons
System Environment/Kernel
System Environment/Libraries
System Environment/Shells
UnspecifiedNow to filter using group we can run following command:
$ rpm -qg "Applications/Text"
gawk-4.0.2-4.el7_3.1.x86_64
sed-4.2.2-5.el7.x86_64
grep-2.20-3.el7.x86_64
diffutils-3.3-4.el7.x86_64
less-458-9.el7.x86_64For querying on a raw rpm package -p is used. For querying documentation files in a uninstalled rpm package we
have to use following command:
$ rpm -qdp tree-1.6.0-10.el7.x86_64.rpm
/usr/share/doc/tree-1.6.0/LICENSE
/usr/share/doc/tree-1.6.0/README
/usr/share/man/man1/tree.1.gzQuery Format
We can format output of package listing using --query-format or --qf filter. These filters takes tags. List of tags
can be found using --querytags command:
$ rpm --querytags
ARCH
ARCHIVESIZE
BASENAMES
BUGURL
BUILDARCHS
# ... (Showing first 5 lines of 205 lines)Now we can format list output like below:
$ rpm -qa --qf "%{NAME} %{SIZE}\n"
selinux-policy-targeted 20055219
grub2-common 3915374
kexec-tools 774283
kbd-legacy 503608
openssh-clients 2651616For formatting an array [] is wrapped around the tag.
$ rpm -ql --qf "[%{FILENAMES} %{FILEMODES}\n]" bash
/etc/skel/.bash_logout 33188
/etc/skel/.bash_profile 33188
/etc/skel/.bashrc 33188
/usr/bin/alias 33261
/usr/bin/bash 33261
# ... (Showing first 5 lines)Some tag can take additional parameter for rendering different type of output. Here we changed output type of FILEMODES using :perms tag type.
$ rpm -ql --qf "[%{FILENAMES} %{FILEMODES:perms}\n]" bash
/etc/skel/.bash_logout -rw-r--r--
/etc/skel/.bash_profile -rw-r--r--
/etc/skel/.bashrc -rw-r--r--
/usr/bin/alias -rwxr-xr-x
/usr/bin/bash -rwxr-xr-x
# ... (Showing first 5 lines)Verify Files
rpm can also report changes in configuration file. Lets first list the configuration file of bash package.
$ rpm -qc bash
/etc/skel/.bash_logout
/etc/skel/.bash_profile
/etc/skel/.bashrcNow lets try to verify configuration files using -V options.
$ rpm -V bashIt prints nothing, meaning configuration file is same as installed configuration. Now change /etc/skel/.bash_profile file and
rerun the command:
$ vi /etc/skel/.bash_profile
$ rpm -V yum
S.5....T. c /etc/skel/.bash_profileIts printing in following format
CHANGE_DETAILS FILE_TYPE FILE_PATH
CHANGE_DETAILS is a string in SM5DLUGTP format. Each character denotes a change type.
S.5….T. means /etc/skel/.bash_profile file is different in length (S), MD5 (5) and access time (T) from original
configuration file.
| Option | Description |
|---|---|
| S | File size differs from original file |
| M | File permission and mode differs |
| 5 | Differs MD5 hash |
| D | Device major/minor version mismatch |
| L | readlink(2) path mismatch |
| U | User ownership changed |
| G | Group ownership changed |
| T | Access time changed |
| P | Capabilities differ |
FILE_TYPE can be any of following chars:
| Option | Description |
|---|---|
| c | Configuration file |
| d | Documentation file |
| g | Ghost file (Files doesn’t included in package) |
| l | Licence file |
| r | Readme file |
Miscellaneous
rpm can also verify MD5 and signature of a package using -K option:
$ rpm -K tree-1.6.0-10.el7.x86_64.rpm
tree-1.6.0-10.el7.x86_64.rpm: rsa sha1 (md5) pgp md5 OKIn rpm public keys are also installed as packages. Each public key installed as separated package. Details can be viewed
of available public keys like normal package using -i option:
$ rpm -qa gpg-pubkey
gpg-pubkey-f4a80eb5-53a7ff4b
$ rpm -qi gpg-pubkeyNow import another public key using following command:
$ rpm --import <PUB_KEY>
$ rpm -qa gpg-pubkey
gpg-pubkey-f4a80eb5-53a7ff4b
gpg-pubkey-b0c18a82-81b1e91cIf we need to rebuild rpm local database of packages, following command can be used:
$ sudo rpm --rebuilddbLocal database in located in /var/lib/rpm/ directory.
Tools Version
- RPM version 4.11.3