dnf Command: Installing, Updating and Removing Packages, and How It Differs from yum

Test environmentRHEL familyAlmaLinux 9.8root accountChecked 2026-10-28

The dnf command is a package management command for searching, installing, updating and removing packages on RHEL-based Linux. On AlmaLinux 9, typing yum runs the same program. On an AlmaLinux 9 server, I actually ran search, info, provides and history, and checked in the output where search, info and provides each look when finding packages, and what history keeps as a record of past operations.

I did not run commands that change the system, such as installing, removing or updating. Their behavior was checked against the official DNF documentation and the operation history already on the server.

1️⃣ How the dnf Command Relates to yum

It is easy to assume that typing yum runs the old yum, but on AlmaLinux 9 both yum and dnf are links to the same executable, dnf-3.

ls -l /usr/bin/yum /usr/bin/dnf
lrwxrwxrwx 1 root root 5 May 21 04:48 /usr/bin/dnf -> dnf-3
lrwxrwxrwx 1 root root 5 May 21 04:48 /usr/bin/yum -> dnf-3

The only difference between yum and dnf is the name you type; the subcommands and options are the same whichever one you use. Running search htop with yum and with dnf also produced identical output.

According to the official DNF documentation [Changes in DNF CLI compared to YUM], update and upgrade do the same thing, and the documentation recommends upgrade.

On older distributions without dnf, you use the yum command as is. The subcommand names in this post, such as install, search and history, are the same in yum.

2️⃣ Finding Packages with the dnf Command: search, info, provides

When you don't know the exact package name of the program you want to install, run search with a single word. search looks for the word in package names and summaries (Summary) and puts the package whose name matches exactly at the top.

dnf search htop
Last metadata expiration check: 0:21:53 ago on Wed Oct 28 15:24:31 2026.
========================== Name Exactly Matched: htop ==========================
htop.x86_64 : Interactive process viewer

htop has only one package with exactly that name, so the result ended with a single line under [Name Exactly Matched].

dnf search wget
Last metadata expiration check: 0:22:35 ago on Wed Oct 28 15:24:31 2026.
========================== Name Exactly Matched: wget ==========================
wget.x86_64 : A utility for retrieving files using the HTTP or FTP protocols
========================= Name & Summary Matched: wget =========================
perl-HTTP-Tinyish-Wget.noarch : HTTP::Tinyish wget backend
wget2-devel.x86_64 : Libraries and header files needed for using wget2 libraries
wget2-libs.x86_64 : Runtime libraries for GNU Wget2
============================== Name Matched: wget ==============================
wget2.x86_64 : An advanced file and recursive website downloader

A word that appears in several packages, like wget, came out split into three groups: exact name matches, matches in both the name and the summary, and matches in the name only.

search does not look at the description (Description) text, so it won't help when the word appears only in the description. In that case, adding the [--all] option widens the search to the description and URL.

Once you know the package name, use info to check its version, size and which repository it comes from.

dnf info htop
Last metadata expiration check: 0:22:37 ago on Wed Oct 28 15:24:31 2026.
Available Packages
Name         : htop
Version      : 3.3.0
Release      : 1.el9
Architecture : x86_64
Size         : 198 k
Source       : htop-3.3.0-1.el9.src.rpm
Repository   : epel
Summary      : Interactive process viewer
URL          : http://hisham.hm/htop/
License      : GPLv2+
Description  : htop is an interactive text-mode process viewer for Linux, similar to
             : top(1).

htop, which is not installed yet, appears in info htop under [Available Packages] with version 3.3.0 and repository epel. htop exists only in the epel repository, so running search again without epel returns nothing.

dnf info wget
Last metadata expiration check: 0:22:38 ago on Wed Oct 28 15:24:31 2026.
Installed Packages
Name         : wget
Version      : 1.21.1
Release      : 11.el9_8
Architecture : x86_64
Size         : 3.1 M
Source       : wget-1.21.1-11.el9_8.src.rpm
Repository   : @System
From repo    : appstream
Summary      : A utility for retrieving files using the HTTP or FTP protocols
URL          : http://www.gnu.org/software/wget/
License      : GPLv3+
Description  : GNU Wget is a file retrieval utility which can use either the HTTP or
             : FTP protocols. Wget features include the ability to work in the
             : background while you are logged out, recursive retrieval of
             : directories, file name wildcard matching, remote file timestamp
             : storage and comparison, use of Rest with FTP servers and Range with
             : HTTP servers to retrieve files over slow or unstable connections,
             : support for Proxy servers, and configurability.

wget, which is already installed, appeared under [Installed Packages]. Repository was @System, and the repository it was downloaded from at install time was listed as appstream on the [From repo] line.

Conversely, when you only know a file name and not which package contains it, give provides the file path.

dnf provides /usr/bin/tree
Last metadata expiration check: 0:22:40 ago on Wed Oct 28 15:24:31 2026.
tree-1.8.0-10.el9.x86_64 : File system tree viewer
Repo        : @System
Matched from:
Filename    : /usr/bin/tree

tree-1.8.0-10.el9.x86_64 : File system tree viewer
Repo        : baseos
Matched from:
Filename    : /usr/bin/tree

Searching for /usr/bin/tree returned two groups: the installed tree package (@System) and the one in the repository (baseos). The Filename under [Matched from] is the path that actually matched. If you give only a file name without a path, dnf searches again with /usr/bin/ and /usr/sbin/ prepended, and if that still finds nothing, it ends with the error below.

dnf provides nosuchfile
Last metadata expiration check: 0:22:41 ago on Wed Oct 28 15:24:31 2026.
Error: No matches found. If searching for a file, try specifying the full path or using a wildcard prefix ("*/") at the beginning.

The error message tells you to give the full path or prepend the wildcard [*/]. The diagram below compares, step by step, what each of the three commands takes as input and where it looks.

🧭 Where the three package-finding commands look
Explainer diagram
🔍 Command
$ dnf search htopinfo htopprovides /usr/bin/tree
① InputhtopA single wordhtopPackage name/usr/bin/treeFile path
➜
② Where it looksPackage name and summary (Summary)Finds every package in all repositories that contains the word.Metadata of a single packageShows installed and installable packages separately.File lists provided by packagesWorks back to the package that contains the file at that path.
➜
③ OutputList of matching packageshtop.x86_64 : Interactive process viewerVersion, size, repository, descriptionVersion 3.3.0, Size 198 k, Repository epelPackage that owns the filetree-1.8.0-10.el9.x86_64, @System, baseos
search looks for the word in package names and summaries and lists the results starting with exact name matches.
info shows the version, size and source repository of a single package. For an installed package, the Repository field shows @System.
provides works back from a file path to the package. The installed side (@System) and the repository side (baseos) are listed separately.

3️⃣ Installing, Removing and Updating Packages: install, remove, upgrade

Install the package you found with install. dnf installs not only the package you specify but also the dependency packages it needs, all at once.

dnf install htop

According to the official documentation, dnf prints the list of packages to install (the transaction summary) and then asks whether to continue; with [-y], it proceeds without asking.

You can check in advance which dependency packages an installation needs with repoquery [--requires].

dnf repoquery --requires htop
Last metadata expiration check: 0:22:59 ago on Wed Oct 28 15:24:31 2026.
libc.so.6(GLIBC_2.34)(64bit)
libcap.so.2()(64bit)
libhwloc.so.15()(64bit)
libm.so.6()(64bit)
libm.so.6(GLIBC_2.2.5)(64bit)
libm.so.6(GLIBC_2.29)(64bit)
libncursesw.so.6()(64bit)
libnl-3.so.200()(64bit)
libnl-3.so.200(libnl_3)(64bit)
libnl-genl-3.so.200()(64bit)
libnl-genl-3.so.200(libnl_3)(64bit)
libtinfo.so.6()(64bit)
rtld(GNU_HASH)

With [--requires] alone, you only get the names of the libraries htop requires. To see which packages contain those libraries, use the next command.

dnf repoquery --requires --resolve htop
Last metadata expiration check: 0:23:01 ago on Wed Oct 28 15:24:31 2026.
glibc-0:2.34-283.el9_8.i686
glibc-0:2.34-283.el9_8.x86_64
hwloc-libs-0:2.4.1-6.el9_7.x86_64
libcap-0:2.48-10.el9_8.1.x86_64
libnl3-0:3.11.0-1.el9.x86_64
ncurses-libs-0:6.2-12.20210508.el9.x86_64

Adding [--resolve] turns them into the names of the packages that provide those libraries. Of these, hwloc-libs was not on the test server, so installing htop installs it as well.

remove deletes the specified package together with the packages that depend on it, and with the default settings it also removes dependency packages that are no longer needed.

dnf remove htop

Even if you remove only htop, dependency packages that no other package needs, such as hwloc-libs installed for htop, are removed along with it.

Packages that were once installed as dependencies but are no longer needed by any package are removed by autoremove. Check the list of packages to be removed first with list [--autoremove].

dnf list --autoremove
Last metadata expiration check: 0:23:09 ago on Wed Oct 28 15:24:31 2026.
Autoremove Packages
cmake-rpm-macros.noarch            3.31.8-3.el9                       @appstream
grub2-tools-efi.x86_64             1:2.06-126.el9_8.alma.1            @baseos
grub2-tools-extra.x86_64           1:2.06-126.el9_8.alma.1            @baseos
libatomic.x86_64                   11.5.0-14.el9.alma.1               @baseos
libvisual.x86_64                   1:0.4.0-34.el9                     @appstream
libwayland-server.x86_64           1.21.0-1.el9                       @appstream
dnf autoremove

On the test server, the list showed 6 packages, and autoremove removes all 6 at once.

To check whether new versions of installed packages are available, use check-update. If you add a package name, only that package is checked.

dnf check-update libavif libdav1d
Last metadata expiration check: 0:52:20 ago on Wed Oct 28 15:24:31 2026.

libavif.x86_64                          1.1.1-3.el9                         epel
libdav1d.x86_64                         1.5.4-1.el9                         epel

The command above with libavif and libdav1d ended with exit code 100 because both had new versions. check-update exits with 100 when updates are available, 0 when there are none and 1 on error, so you can use it as a branch condition in scripts.

Adding a package name to list shows the installed version and the new version in the repository together. With updateinfo list, you can see which advisory the update belongs to.

dnf list libavif
Last metadata expiration check: 0:52:21 ago on Wed Oct 28 15:24:31 2026.
Installed Packages
libavif.x86_64                        0.11.1-5.el9                         @epel
Available Packages
libavif.x86_64                        1.1.1-3.el9                          epel

For libavif, the installed 0.11.1-5.el9 appeared under [Installed Packages] and the repository's 1.1.1-3.el9 separately under [Available Packages].

dnf updateinfo list libavif
Last metadata expiration check: 0:52:24 ago on Wed Oct 28 15:24:31 2026.
FEDORA-EPEL-2026-d611eab94a bugfix libavif-1.1.1-3.el9.x86_64

That new version was an update for the bugfix advisory FEDORA-EPEL-2026-d611eab94a. Security updates show a severity and Sec. in the same place, like [Moderate/Sec.].

Run updates with upgrade. upgrade installs new versions only as far as the dependencies allow, so the version shown by check-update may not be the one that actually gets installed.

dnf upgrade libavif

If you add a package name, only that package and the dependency packages it needs are upgraded to new versions.

dnf upgrade

If you omit the name, all installed packages are targeted. The flow of printing a transaction summary and asking whether to continue is the same as with install, and each transaction you run is recorded with a number in history.

4️⃣ dnf Command Repository List: repolist

The place where search and install look for packages is the repository. repolist prints the id and name of the currently enabled repositories.

dnf repolist
repo id             repo name
appstream           AlmaLinux 9 - AppStream
baseos              AlmaLinux 9 - BaseOS
epel                Extra Packages for Enterprise Linux 9 - x86_64
epel-cisco-openh264 Extra Packages for Enterprise Linux 9 openh264 (From Cisco) - x86_64
extras              AlmaLinux 9 - Extras
nginx-stable        nginx stable repo
remi-modular        Remi's Modular repository for Enterprise Linux 9 - x86_64
remi-safe           Safe Remi's RPM repository for Enterprise Linux 9 - x86_64

It is easy to assume that a repository missing from the list doesn't exist on the server, but repolist's default output shows only enabled repositories. Adding [--all] also prints disabled repositories along with a status column. On the test server, all three AlmaLinux 9 CRB repositories were disabled.

dnf repolist --all | grep -i crb
crb                           AlmaLinux 9 - CRB                         disabled
crb-debuginfo                 AlmaLinux 9 - CRB - Debug                 disabled
crb-source                    AlmaLinux 9 - CRB - Source                disabled

Use repoinfo to check a single repository's package count, mirror address, metadata expiration time and configuration file location.

dnf repoinfo baseos
Last metadata expiration check: 0:22:55 ago on Wed Oct 28 15:24:31 2026.
Repo-id            : baseos
Repo-name          : AlmaLinux 9 - BaseOS
Repo-status        : enabled
Repo-revision      : 1793090609
Repo-updated       : Tue Oct 27 17:43:29 2026
Repo-pkgs          : 3458
Repo-available-pkgs: 3458
Repo-size          : 21 G
Repo-mirrors       : https://mirrors.almalinux.org/mirrorlist/9/baseos
Repo-baseurl       : http://aws.repo.almalinux.org/almalinux/9.8/BaseOS/x86_64/os/ (9 more)
Repo-expire        : 86400 second(s) (last: Wed Oct 28 15:24:26 2026)
Repo-filename      : /etc/yum.repos.d/almalinux-baseos.repo
Total packages: 3458

repoinfo baseos showed 3,458 packages, with the metadata set to be rechecked every 86,400 seconds (one day). The .repo file on the [Repo-filename] line is this repository's configuration file. The [--set-enabled] and [--set-disabled] options, which enable and disable repositories, are used with the config-manager command from dnf-plugins-core.

5️⃣ dnf Command History and Undo: history

After many installs and removals, it becomes hard to track what you changed and when, but dnf numbers each transaction and records it in history. Adding a package name shows only the transactions that changed that package.

dnf history list tmux
ID     | Command line             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
    51 | install -y tmux          | 2026-10-15 20:40 | Install        |    1

The output narrowed down to tmux left just one line: transaction 51, which installed tmux. A range of numbers is written with two dots, like [50..51].

dnf history list 50..51
ID     | Command line             | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------
    51 | install -y tmux          | 2026-10-15 20:40 | Install        |    1
    50 | -y -q install mlocate    | 2026-10-07 19:39 | Install        |    1 EE

The number in the [Altered] column is the number of packages changed. Line 50 ended with [EE], which means the transaction finished but produced warning or error output.

Use history info to check a single transaction's command line, changed packages and return code.

dnf history info 51
Transaction ID : 51
Begin time     : Thu Oct 15 20:40:51 2026
Begin rpmdb    : d3db9c92a9d0f6ef9a7a1404552bb76e9d56ba7602b1fce73fa5a62170d33c5c
End time       : Thu Oct 15 20:40:51 2026 (0 seconds)
End rpmdb      : a862c33ee6a2f2d0479e4dc2631907dee47591c5b6795551b755c6cd090ac1df
User           : root <root>
Return-Code    : Success
Releasever     : 9
Command Line   : install -y tmux
Persistence    : Persist
Comment        :
Packages Altered:
    Install tmux-3.2a-5.el9.x86_64 @baseos

Opening transaction 51 showed the command that was run, install -y tmux, kept as is under [Command Line]. [Packages Altered] listed the installed tmux with the repository @baseos, and [Return-Code] showed Success. If you omit the number, the most recent transaction is shown.

If you installed something by mistake, add the transaction number to history undo to perform the reverse of that transaction. rollback returns the package state to just after the specified transaction.

dnf history undo 51

Transaction 51 was the tmux installation, so undo 51 becomes a reverse transaction that removes tmux.

dnf history rollback 50

rollback 50 reverts every transaction run after 50, up to the last one, so the result can differ from undo 51, which removes only tmux.

According to the official documentation, if any package cannot be reverted, undo and rollback end without changing anything. They do not stop with an error even if changes made directly with rpm are missing from the history.

🔲 dnf Command Simulator

In the simulator below, you can type the search, info, provides, repolist and history commands yourself and check the output. Typing yum gives the same results.

dnf Command Simulatordnf 4.14.0
[root@server work]#
Use the ↑↓ keys to recall commands you typed earlier.

🔢 FAQ & Recommended Content

It is the time the local copy of the repository metadata was last checked. According to the official documentation, the metadata is downloaded again once the metadata_expire time set for each repository has passed. Commands that don't strictly need up-to-date information, such as search and provides, use the local copy even after it has expired. Adding [--refresh] forces a fresh download, and [-C] uses only the cache.

Trying a nonexistent command like foo produced a [No such command] error along with a hint to try installing a plugin in the form [dnf install dnf-command(name)]. This is because some subcommands are added by plugin packages such as dnf-plugins-core. If it was a typo, check the list of commands with [dnf --help].

rpm -q reads only the database of packages installed on the server (RPMDB) and prints that package's version, or replies [package htop is not installed] if it is not there. dnf list –installed prints the same database with repository information added, so each installed package is shown next to the repository it came from (@epel). Using dnf list without [--installed] also prints new versions in the repositories.

🧭 Package Commands: Recommended Reading 6 posts · 2 references
🗂️ Package commands
📄 YUM concepts and basic commands 📄 dnf command 📄 yum-config-manager command 📄 RPM vs YUM
📄 apt · apt-get commands 📄 Installing snapd

ℹ️ Affiliate Disclosure
This site's content contains affiliate links. When a visitor buys a product or service through one of them, the site receives a commission from the seller. The amount the buyer pays(it goes down during event discounts ↓)does not go up. Posted prices, discounts, and stock reflect the time of writing and may differ, so confirm with the seller before buying. Products are chosen and reviewed by our own standards, and commissions do not affect the order or content of reviews.

Leave a Reply

Your email address will not be published. Required fields are marked *

Prove your humanity: 0   +   4   =