1 of 4

Software ManagementLesson 1 of 4

Asking questions of the RPM database

Find which package owns a file, what a package contains, where its configuration lives and whether it has been altered.

  • rpm
  • rpm -q
  • rpm -qa
  • rpm -qi
  • rpm -ql
  • rpm -qf
  • rpm -qc
  • rpm -qd
  • rpm -V
  • rpm -qp
  • rpm -K

40 min5 exercises

After this lesson you can

  • Use the query options of rpm to find a package, its files, configuration files and documentation.
  • Find the package that provides a file, and inspect an RPM file before installing it.
  • Verify installed files against the database and read the result.

The idea

Every file installed from a package is recorded in the RPM database. That makes rpm a question-answering tool: which package put this here, what else did it install, what are its config files, did anyone change them? Learn the queries and you can understand an unfamiliar server quickly.

A package name looks like chrony-4.6.1-1.el10.x86_64: name, version, release (the distributor’s build number, .el10 is RHEL 10) and architecture.

All query commands are rpm -q plus a selector. Add a second letter for what to show.

CommandAnswers
rpm -q NAMEIs it installed, which version?
rpm -qaEvery installed package (pipe to grep, wc -l)
rpm -qi NAMEDescription, version, build date, vendor, signature
rpm -ql NAMEEvery file the package installed
rpm -qc NAMEOnly its configuration files
rpm -qd NAMEOnly documentation files (man pages, README)
rpm -qf /path/fileWhich installed package owns this file
rpm -q --scripts NAMEInstall and removal scripts
rpm -q --requires NAMEWhat it depends on
rpm -V NAMEHas any of its files changed since install?

Add p to query a package file instead of the database: rpm -qip file.rpm, rpm -qlp file.rpm. This lets you look inside an RPM before you install it.

rpm -qf only knows about files that are installed. For “which package would give me this command” use dnf provides, which searches the repositories:

dnf provides /usr/sbin/semanage
dnf provides '*/semanage'

Try it

rpm -q bash chrony nonexistent
bash-5.2.26-6.el10.x86_64
chrony-4.6.1-1.el10.x86_64
package nonexistent is not installed
rpm -qf /etc/ssh/sshd_config
openssh-server-9.9p1-5.el10.x86_64
rpm -qc chrony
rpm -qd chrony | head -3
/etc/chrony.conf
/etc/chrony.keys
/etc/logrotate.d/chrony
/usr/share/doc/chrony/FAQ
/usr/share/doc/chrony/NEWS
/usr/share/doc/chrony/README

Run rpm -qc before you edit anything under /etc: it tells you exactly which files the package expects you to customise.

Look before you install

dnf download tree
rpm -qip tree-*.rpm | head -4
rpm -qlp tree-*.rpm
rpm -K tree-*.rpm
Name        : tree
Version     : 2.1.0
Release     : 6.el10
Architecture: x86_64
/usr/bin/tree
/usr/share/doc/tree/LICENSE
/usr/share/doc/tree/README.md
/usr/share/man/man1/tree.1.gz
tree-2.1.0-6.el10.x86_64.rpm: digests signatures OK

rpm -K checks digests and the GPG signature. If it reports NOKEY, the signing key is not imported yet (rpm --import KEYFILE); the package is not necessarily bad, but it is unverified.

Verify installed files

rpm -V openssh-server
echo '# test' | sudo tee -a /etc/ssh/sshd_config
rpm -V openssh-server
# test
S.5....T.  c /etc/ssh/sshd_config

The first command prints nothing because nothing differs (the # test line is tee echoing what it appended). The nine characters stand for: Size, Mode, 5 (digest), Device, Link, User, Group, Time, Pcapabilities. A dot means unchanged. The c marks a configuration file. A changed config file is normal, a changed binary (/usr/bin/...) deserves attention.

Going further

rpm -qa --last | head lists packages by install time, newest first: the quickest way to answer “what changed on this server recently”. rpm -q --qf '%{NAME} %{VERSION}\n' PACKAGE formats the output, and rpm -qa --qf '%{SIZE} %{NAME}\n' | sort -n | tail finds the largest packages. rpm -ivh and rpm -e install and erase directly, but they do not resolve dependencies; use dnf for those and keep rpm for questions.

Practice

0 of 5 done

Do these on your own system. They get harder. Check each result, then tick it off.

  1. Warm-up

    Is it installed, and which version?

    Check whether bash, chrony and nonexistent are installed. List how many packages are installed in total.

    Check your result

    rpm -q bash chrony nonexistent prints a name-version-release for the first two and package nonexistent is not installed for the third. rpm -qa | wc -l prints a number.

    Hint

    rpm -q NAME... can take several names. rpm -qa lists everything.

    Solution
    rpm -q bash chrony nonexistent
    rpm -qa | wc -l
  2. Practice

    Which package owns this file?

    Find the package that owns /etc/ssh/sshd_config and the package that owns /usr/bin/passwd. Then find which package would provide /usr/sbin/semanage even though it is not installed.

    Check your result

    rpm -qf names openssh-server and passwd. dnf provides /usr/sbin/semanage names policycoreutils-python-utils.

    Hint

    rpm -qf PATH asks about installed files only. dnf provides searches the repositories, and */semanage also works.

    Solution
    rpm -qf /etc/ssh/sshd_config
    rpm -qf /usr/bin/passwd
    dnf provides /usr/sbin/semanage
  3. Practice

    What does this package contain?

    For chrony, show its summary, version and install date. List its configuration files and its documentation files separately. Count how many files it installs.

    Check your result

    rpm -qi shows Name, Version, Install Date and Summary. rpm -qc chrony includes /etc/chrony.conf. rpm -qd chrony lists man pages. rpm -ql chrony | wc -l prints a number.

    Hint

    -i info, -c config files, -d documentation, -l all files. Combine with -q NAME.

    Solution
    rpm -qi chrony | grep -E '^(Name|Version|Install Date|Summary)'
    rpm -qc chrony
    rpm -qd chrony
    rpm -ql chrony | wc -l
  4. Practice

    Look inside an RPM file before installing it

    Download the tree package without installing it (dnf download tree). Display its description, its file list and its scripts using the -p form of the query options, and check its signature.

    Check your result

    rpm -qip tree.rpm prints the package info, rpm -qlp lists /usr/bin/tree, and rpm -K tree.rpm reports digests signatures OK (or OK after the Red Hat key is imported).

    Hint

    Add p to query a package file rather than the database. rpm -qp --scripts FILE shows install scripts.

    Solution
    mkdir -p ~/lab/rpms && cd ~/lab/rpms
    dnf download tree
    rpm -qip tree*.rpm | head -12
    rpm -qlp tree*.rpm
    rpm -qp --scripts tree*.rpm
    rpm -K tree*.rpm
  5. Challenge

    Has anything been changed?

    Verify the openssh-server package. Add a harmless comment line to /etc/ssh/sshd_config, verify again, and explain every character of the line that rpm -V prints for the file. Restore the original file afterwards.

    Check your result

    Before the edit rpm -V openssh-server prints nothing. After it prints a line such as S.5....T. c /etc/ssh/sshd_config: S size, 5 digest, T modification time differ, and c marks a configuration file.

    Hint

    Back up the file first with cp -a. Each position in the nine-character string is one attribute; a dot means that attribute matches.

    Solution
    sudo cp -a /etc/ssh/sshd_config /root/sshd_config.orig
    rpm -V openssh-server
    echo '# test comment' | sudo tee -a /etc/ssh/sshd_config
    rpm -V openssh-server
    sudo cp -a /root/sshd_config.orig /etc/ssh/sshd_config
    rpm -V openssh-server