TT Lab
Get started
Learn Learning paths Courses

Package Management

dpkg Does Not Resolve the Graph

Continue in TT Lab

In one line

apt is a tool that decides what to install, and dpkg is a tool that installs what has been decided. Once you know this division of labor, you immediately understand why dpkg -i stops with a dependency error.

Why this exists

If you download one .deb file and install it with dpkg -i, you get a message like this.

dpkg: dependency problems prevent configuration of labhub-extra:
 labhub-extra depends on labhub-tool (>= 1.2.0); however:
  Package labhub-tool is not installed.

dpkg does not know the repository. It does not even know where to fetch what from. It merely unpacks the file it is given, and if the dependencies are not satisfied, leaves it in a "not configured" state. That is why apt-get -f install (fix broken) exists as its partner. It means "apt, look at the repository and finish resolving the unresolved state dpkg left behind."

How it works

A .deb file is actually an ar archive. It holds three pieces.

Piece Contents
debian-binary Format version (usually 2.0)
control.tar.* The control file and maintainer scripts (preinst/postinst/prerm/postrm), conffiles, md5sums
data.tar.* The files that are actually unpacked onto the filesystem

Installation has two steps, unpack → configure. unpack extracts the data, and configure runs postinst to do finishing work such as registering the service. The first two characters of the dpkg -l output show this state.

Mark Meaning
ii Install requested + install complete (normal)
iU Install requested + only unpacked (configure failed)
rc Removal requested + only configuration files remain
pn Not installed (purged)

It is common to overlook the rc state. The answer to "I removed it, so why is the configuration still there?" is here.

dpkg's query commands go in three directions.

dpkg -l                       # 무엇이 설치돼 있나
dpkg -L coreutils             # 이 패키지가 어떤 파일을 깔았나
dpkg -S /usr/bin/ls           # 이 파일은 누가 깔았나
dpkg -s coreutils             # 이 패키지의 메타데이터는 무엇인가
dpkg-query -W -f='${Package} ${Version}\n'

The third (-S) is the one used most often in practice. When you meet a binary of unknown origin on an unfamiliar server, it separates in one second whether a package installed it or a person placed it by hand. If dpkg -S finds nothing, that file is outside package management, and such files tend not to disappear on upgrades and not to be captured in backups.

What it looks like in the field

A configuration file conflict. During an upgrade, a Configuration file '/etc/foo.conf' ... What would you like to do? prompt appears. dpkg remembers the md5 of files registered in conffiles, so it can tell whether a person edited them. If you carelessly choose "package maintainer's version" at this prompt, the tuning you put in by hand disappears entirely. In automation scripts you have to state the policy explicitly with -o Dpkg::Options::="--force-confold".

Configuration files are treated specially

The files listed in conffiles inside a .deb follow different rules from the rest. If you do not know these rules, you meet situations where the configuration vanished after an update or, conversely, the new configuration never came in, and both have the same cause.

When it updates, dpkg compares three things: the content the package originally put in, the content on disk now, and the content the new package wants to put in.

The third case is where the problem lies. In an automated update nobody sees that question, so the service runs with the configuration entries the new version needs missing from our file. It quietly runs on defaults and later shows up as strange symptoms. That is why you need a procedure that, after an update, scans for whether .dpkg-dist, .dpkg-new, or .ucf-dist files have appeared.

The relationship between the rc state and configuration files is explained here too. As we saw earlier, the reason configuration remains even after you delete a package is that remove does not touch conffiles, and purge deletes those as well. So if you reinstall the same package, the old configuration comes back to life, and "I reinstalled cleanly but get the same problem" comes from here.

Finally, if you plan to manage a configuration file outside the package, it is better to put it in a separate file that is not in conffiles at all. This is why most packages provide a directory such as conf.d/. The files in it are not owned by the package, so an update does not touch them, and the three-way comparison itself never happens.

What you will do in the next lab

You query the system with dpkg -L/-S/-s, and build a .deb yourself from a fixture directory and even install it. Once you have built a package, you know for certain what is inside it.