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.rpm
Here 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.rpm
Install/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.rpm
rpm
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.rpm
Now 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_64
We 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.rpm
Now we can install nmap
without any error using following command:
$ sudo -i nmap-6.40-16.el7.x86_64.rpm
Remove Package
We can remove a package using --erase
or -e
option like below:
$ sudo rpm -e nmap
Note 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 nmap
Query 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 bash
For 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/.bashrc
Dependencies 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-1
We 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.noarch
We 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
Unspecified
Now 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_64
For 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.gz
Query 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 2651616
For 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/.bashrc
Now lets try to verify configuration files using -V
options.
$ rpm -V bash
It 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_profile
Its 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 OK
In 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-pubkey
Now import another public key using following command:
$ rpm --import <PUB_KEY>
$ rpm -qa gpg-pubkey
gpg-pubkey-f4a80eb5-53a7ff4b
gpg-pubkey-b0c18a82-81b1e91c
If we need to rebuild rpm
local database of packages, following command can be used:
$ sudo rpm --rebuilddb
Local database in located in /var/lib/rpm/
directory.
Tools Version
- RPM version 4.11.3