Bash Shell

Have you ever broken apt? For seasoned Linux professionals, it’s quite common (about every half year) to unwittingly break apt. If you know a few commands in dpkg, you can often fix the issue more easily! Find out how.

What Are apt and dpkg?

If you’re using a Debian-based distribution like Ubuntu or Mint, your computer uses apt to handle packages. Apt stands for Advanced Packaging Tool, which allows you to install, uninstall, purge, and manage Debian packages.

Besides apt (used at the command line), your computer likely has a higher level/overarching Desktop-based package manager, which simply uses apt, or perhaps dpkg, in the background.

The package manager for Debian dpkg is an alternative to managing packages on Debian-based installations. It’s much more low level than apt, giving you more freedom, but also presenting a higher risk of breaking things.

This is the reason why (unless you’re a seasoned DevOps engineer) I recommend that you use apt at all times, augmenting it with dpkg as soon as you run into issues.

Taking this to step approach gives you the best of both worlds: The stability and ease of use of the apt package manager, with the power and granularity of the dpkg Debian package manager, once you need it.

Let’s say, for example, that you have a package that you just installed, which somehow ended up breaking the apt. Or, perhaps, a package installation accidentally got interrupted.

Whatever the cause, apt is now considered broken, and you’ve already tried things like sudo apt update --fix-missing and sudo apt install --fix-broken to no avail. If so, then …

Welcome to dpkg

When your apt is broken, it’s no fun. If it’s really broken, it’s even less fun. Even if someone knows what they’re doing, it sometimes takes a certain level of art, and definitely, skill, to fix a broken packaging system.

The term “art” is quite applicable, as you get a sense or feeling while you’re running through various troubleshooting steps—especially if you’ve done this often—whether or not something will work out during a reboot.

The risk is always that the packaging system is so badly broken that if you reboot, your Linux instance might not come up again, and that further and potentially still more complex troubleshooting will be required.

I would like to state at this point that all of this can be easily avoided by executing a few simple commands—but regrettably, that’s not the case. The fact is, the more you know, the easier it will be to fix, and the more confidence you’ll have to figure out whether you’re ready for a system reboot or not.

This is where we come to dpkg. The dpkg program allows us much more granular control over all installed packages, and while there’s more risk that something will go amiss, there’s also much more power to change a system in exactly the way that we want to. Let’s dive in.

If you’re interested in Linux in general, you might also like to read our Bash Automation & Scripting three-part series.

Basic dpkg Usage

We can see the packages currently on the system by simply executing dpkg -l. As the output is likely to be very verbose (although normally paginated), you can use a grep to limit the results.

dpkg -l | head -n5 && dpkg -l | grep 'gnome-calculator'
dpkg -l | grep 'gnome-calculator'

Our first dpkg run

The first command is actually a combination of two commands (separated by &&, which literally means: Only execute the second command if the first one is successful).

In the first of these two commands, we take the first five lines (using a pipe | and head -n5), and then, in the second command, we seek to list the output we’re searching for. In this case, we’re searching for the text gnome-calculator.

The secondary line/command under it shows a version that we would normally use. Once someone is familiar with the syntax of the dpkg output, the first five lines are often unnecessary. Note that the first column is referring to (visually) Desired=, with the second column referring to Status=, and the third column to Err?=. If you visually follow the lines, you’ll see how they connect quickly.

As our gnome-calculator is successfully installed without any current errors, there’s no third column code under Err?=. We also note here that uppercase=badis written in the short info relating to the third column. As previously stated, in our case, it’s blank.

The first column shows the desired status, and the second column shows the current status. Both show as i (Install[ed] and Inst[alled] respectively, and this (ii) is the most common sequence you’ll (want to) see. It basically means that everything is fine, that the package is installed, and that there are no issues.

Also note that, in the column descriptions between the parentheses, the uppercase letter indicates the connection between any possible letter seen and the relevant term. For example, consider how f refers to halF-conf, noting the uppercase F in the same.

Let’s now take a look at another output to compare. This time, we’ll leave off the first five lines, and you can get a little more used to reading the output even without the headers.

dpkg -l | grep 'mintwelcome'

dpkg -l | grep 'mintwelcome' output

Here, we see the interesting result of rc, where ii used to be for the gnome-calculator. If you search for the r in the first Desired= column description that we saw above, you can see that it stands for Remove[d], and that c in the second column stands for Conf-files.

Aha! This (mintwelcome, a welcome package on Mint) is a package that we uninstalled at some point, yet the configuration files for the same remain. Let’s purge it!

dpkg --purge 'mintwelcome'
sudo dpkg --purge 'mintwelcome'
dpkg -l | grep 'mintwelcome'

Purging 'mintwelcome' configuration files with dpkg

Note that you can also use the -P shorthand instead of using --purge.

In the first command, we can try to purge mintwelcome without using sudo. However, this won’t work. You need super-user/root-level privileges to uninstall (or install or purge) packages. We can run again using sudo, and our package will be purged.

Note that the term purge is used by both apt as well as by dpkg to indicate that we want to completely purge a package rather than just uninstall it, which will leave any configuration files.

Making Sure

I trust that you might start to appreciate the power, control, and granularity that dpkg can provide you with when managing packages on your Debian-based distribution, such as Ubuntu, or, in this case, Mint. It would be easy, for example, to scan for configuration file remainders of previously uninstalled packages by simply executing:

dpkg -l | grep '^rc'

dpkg listing output for javascript-common configuration files

Before removing any such configuration files, you’ll want to make doubly sure that there are no packages installed with a similar name. For example, in this case, we can run:

dpkg -l | grep 'javascript'

dpkg -l | grep 'javascript' output

Note how we removed the second part of 'javascript-common' to search for 'javascript'.

Safe to remove or not? You can see how great power comes with great responsibility, as always in life. The decision to remove it or not is yours. There are generally three things to always keep at the back of your mind when working with dpkg:

Firstly, you’ll want to check, double-check, and triple-check to be sure. For example, in the first output above, we might have gone ahead and nonchalantly removed javascript-common without checking to see whether there were any other Javascript packages on the system.

Was it the best course of action? Perhaps, but the surety/confidence level surely went down as soon as we did our first check, as there definitely are other Javascript packages on the system.

Also, note that there is really nothing broken here. It’s fine to leave the configuration files for this seemingly removed package. The old adage “If it ain’t broke, don’t fix it” would surely seem to apply in this case. It’s a good one to keep in mind when using dpkg.

Secondly, it’s important to remember that apt is a package manager that keeps all connections (i.e. versions and dependencies) between packages in mind when installing, uninstalling, or purging packages.

This isn’t the case for dpkg, which is much more package-based. There’s more granularity, but also more risk of breaking things. If a package relies on another or on a library, someone is sure to break things simply by uninstalling the main package using dpkg.

Thirdly, most Linux packages have many dependencies. It’s thus not recommended to simply use dpkg for standard package management, reiterating our original advice to use apt by default and swap to dpkg when it becomes necessary.

To remove/uninstall a package rather than purge it (i.e. leave the configuration files), you can use the --remove (or -r) option to dpkg. To verify a package, use --verify (or -V). The --audit (or -C) option against a package does database sanity and consistency checks for the package (or for all packages if no package is specified).

For more options, see man dpkg executed from your terminal. There are also specific, more complex commands that can be used for various packaging system issues. For these, it’s usually best to employ your favorite search engine for the specific issue or situation seen at the time that it occurs. Often, someone else has already run into it and documented the details. If you find out something new, take a few minutes to log your findings on some forum or relevant discussion thread.

Wrapping up

In this article, we started exploring dpkg and how it can help us with granular package management, unlike apt, which will handle packages and all their dependencies. Remember, in these complex package management issue debugging situations, with great power comes great responsibility.

We also looked at how to follow a more risk-averse approach whilst realizing that in-depth package management debugging is similar to art, and the better a painter is, the more successful the painting—ahem, the reboot will be.

Profile Photo for Roel Van de Paar Roel Van de Paar
Roel has 25 years of experience in IT & business, 9 years of leading teams, and 5 years in hiring & building teams. He worked for companies like Oracle, Volvo, Sun, Percona, Siemens, Karat, and now MariaDB in various senior, principal, lead, and managerial roles.
Read Full Bio »